WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序

现在我们创建一个Lig工程 - Litelog

2.1 创建Lig服务

_________________________________________________________________________________

不好意思。我尽最大的程度说明清楚问题。
Lig这些内容是写

How to use the WCF rather than to explain what the WCF is.

所以以跳跃性比较大,如果有些WCF基础最好。如果想知道Details,建议看Artech的《WCF全面解析》或search他的cnblog,这是最好的解决问题之道。

不过有一点你会高兴,这儿会提供这些文章与源代码工程.

OpenSource codes provided with you here .Thanks

2.1 .1Lig工程创建 - Litelog

如图 2.1 .1所示
创建一个名为Litelog的空solution,同时添加如下四个新建项目:

1) LigServer:  WCF服务端程序。控制台程序。Console Application
2) ILigAgent:  WCF服务接口(服务契约)。库类代码。ClassLibrary
3) LigAgent:  WCF服务实现,继承ILigAgent,借宿于LigServer进程。库类代码。ClassLibrary
4) LigClient:  WCF客户端测试用例。控制台程序。Console Application

WCF创建遵循SOA标准中要求对契约编程,而不是实现。

WCF通过接口定义服务契约,通过数据契约定义接口出现的参数,通常数据契约(非简单变量)出现的参数会在Server-Client之间共享。

因为WCF是基于特性的编程,如果你了解对象关系模型(ORM) ,就知道.net中所有继承于Attribute类的类是如何影响方法运行的。

图 2.1.1 Lig工程结构

所以,首先,我们看WCF服务接口内部是什么样子的。

2.1.2 创建WCF服务接口 – ILigAgent

在ILigAgent项目中添加两个文件夹:DataMembers与Interfaces,分别用来存放数据契约与服务契约。目前只含LigLevel.cs与ILigAgent.cs两个项目文件。

LigLevel : 枚举变量。Lig日志级别。

    public enum LigLevel{Info = 0,Debug = 1,Warn = 2,Error = 3,Fatal = 4}

图2.1.2  ILigAgent 服务契约结构

ILigAgent : 服务契约。一共含 8 个操作接口。

注意:

1) LigFatal有一个重载方法,这儿显式应用OperationContract特性中的Name属性加以区分。

否则,WCF服务接口中使用默认OperationContract特性是不允许重载方法出现的。在用SvcUtil.exe生成LigAgent代理类时时你会看到

void LigFatal(string message, Exception ex)

变成

void LigFatalex(string message, Exception ex)

了。讲LigServer生存代理类与客户端配置时后面会提到

2)  Initialize用于初始化Lig路径。

SayHelloToServer则用于客户端创建通道(ChannelFactory)成功后测试Server是否在线,在创建LigClient时会解释SayHelloToServer存在的意义。

    [ServiceContract]public interface ILigAgent{[OperationContract]void LigMessage(string message, LigLevel level);[OperationContract]void LigInfo(string message);[OperationContract]void LigDebug(string message);[OperationContract]void LigWarn(string message);[OperationContract]void LigError(string message);[OperationContract(Name = "LigFatal")]void LigFatal(string message);[OperationContract(Name = "LigFatalex")]void LigFatal(string message, Exception ex);[OperationContract]void SayHelloToServer(string message);[OperationContract]void Initialize(string ligPath);}

2.1.3 创建WCF服务

LogAgent

如图2.1.3所示。创建WCF服务实现,实现ILigAgent服务接口。LigAgent将会用于借宿于LigServer进程。

关于服务行为特性说明(ServiceBehavior):

实例模式:PerSession。这儿采用一个代理,一个实例。

并发模式:Multiple。多线程。

这两个参数与WCF并发与实例管理相关。这儿的配置是因Lig的客户可能需要写不同的文件,同时要考虑多个Lig客户端存在会有异步调用的需求,以加快日志书写时间,提高LigServer的性能。从客户端需求与性能上考虑采用一个代理,一个实例,并发模式采用多线程。

图 2.1.3 创建WCF服务实现

2.1.4 LigCore - EmitFileMessage

对于OOP,其中有一条“依赖倒置”原则
其实,对C#本身面言,编程中,我们抽象出的更多的是interface而不是abstract类。

我们个人喜欢用interface而不是单单的abstract类去实践“依赖倒置”原则。但有时还是有例外的,比如累量级的ORM PetaPoco对不同的数据库对象Privider,interface在.net中已经存在,所以我们会写abstract类为所有不同Privider的基类。说多了。

1) 为了减小LigAgent的本身代码负担,我们创建另外一个类,LigCore,专门负责文件书写工作,并用Mutex保证线程操作安全,所有日志操作由EmitFileMessage完成。

2) 同时提供一个EmitFileMessage的非静态重载版本。

(此处文件操作用简单的StreamWriter实现。Log4net采用FileStream + TextWriter实现,同时采用Mutex保证文件操作线程安全)

图2.1.4 LigCore文件操作

public void LigMessage(string message, LigLevel level)
{string formatMsg = LigCore.LiggedTime + level.ToString() + " " + message;new LigCore().EmitFileMessage(formatMsg, this.LigPath, true);
}

EmitFileMessage的非静态重载版本

        public void EmitFileMessage(string message, string fullpath, bool isAppending){StreamWriter writer = null;try{writer = new StreamWriter(fullpath, isAppending);writer.Write(message);writer.Flush();}catch (Exception ex){// ignore}finally{if (writer != null){writer.Close();}writer = null;}}

2.2 创建LigServer

_________________________________________________________________________________

2.2.1 关于Lambda表达式

先暂时不用去理解这儿出现的Lambda表达式:

(sender,e)=>{}

不过有必要说下,Lambda表达式,linq与扩展方法在.net3.0引入的新特性会大在简化你的编程时间。

如果应用Sql,Linq是最佳的方式。

你懂得Lambda表达式在创建临时方法的好处,linq查询对泛型委托的极致应用带来的对for/foreach/while的简化操作,扩展方法对现有类功能扩展的方便之处。如果你构建超时方法,事件处理等通用类,对Lambda表达式,linq查询与扩展方法会变成最常用的操作。

2.2.2 SvcUtil工具生成客户端代理类与客户端配置

1) 启动LigServer,打开控制台,进入SvcUtil.exe所在的目录,输入:

SvcUtil.exe http://127.0.0.1:7023/Lig.vivitue.LigMetadata

2) 回车。如果你对SvcUtil的使用没有问题,你会看到生成的LigAgent.cs文件与output.config配置。把output.config改成App.config后就可以加入到客户端LigClient中使用了。
3)  同时在浏览器中输入http://127.0.0.1:7023/Lig.vivitue.LigMetadata你就能看到LigServer发布的元数据了。

4) 打开Output.config与LigAgent代理类。

不清楚svcutil的,baidu或google下。太多文章讲svcutil如何使用

用过svcutil的人都看过这种东西,看着LigAgent与output.config是不是有些乱?很多人看过这种文件。

我要说的是,对IIS借宿的基于Web访问的WCF服务,这是一种很好的方式,但对window form程序,这并不好,不利于代码后期维护。下面这两个文件在我们的客户端中都不会出现。

我们将采用一种新的方式来编写我们客户端的配置与用接口取代代理类。

图 2.2.1 LigServer

图 2.2.2 SvcUtil工具生成客户端代理类与配置

图 2.2.3 生成的 Output.config与LigAgent代理类

2.2.3 服务端配置文件- App.config

服务端用的配置


创建的WCF项目默认采用App.config或Web.config(IIS服务用)作为服务端与客户端的配置文件。该文件编译后会与*.exe文件放在一起。变成*.exe.config,在WCF配置启动时ServiceHost内部会自动加载。如果想改变配置文件路径与名称,则你得重写ServiceHost类与ChannelFactory<T>类了,后面讲《自定义配置》会解释。

关于WCF配置中WCF服务的行为 behavior

WCF中,定义behavior用于设置服务运行时的特性,此处,我们通过指定ServiceMetadataBehavior使WCF服务对外公布Metadata,这样我们可以通过http形式访问。
同时用SvcUtil.exe工具生存代理类与代理类的配置文件output.config (客户端使用的)。

1) 在WCF中,behavior被定义为Attribute
2) ServiceBehavior与OperationBehavior是最常用的behavior (在前面的接口中你看到的WCF服务接口的特性性应用)

3) 一个WCF服务可以有多种行为

4) 但在配置中,一个WCF服务地址默认情况下只能指定一个行为(behaviorConfiguration),如果想一个WCF服务地址指定多种行为,此时你得扩展ServiceHost类了。
通过ServiceHost中的Description.Behaviors属笥添加多种行为。后面扩展ServiceHost类时会提到ServiceHost中的Description属性。

图 2.2.3 客户端配置

2.3 创建LigClient的代码
_________________________________________________________________________________

2.3.1 在客户端应用ILigAgent – 接口编程

WCF依赖统一的服务接口在客户端与服务端进行通信,我们完全可以用ILigAgent来取代用SvcUtil工具自动生成的代理类LigAgent。

了解这点后,我们可以在LigClient添加ILigAgent接口,而不是应用自动生成了LigAgent代理类,那样代码太乱了,同时不太符合OOP中“依赖倒置”原则采用基于抽象编程的概念。这儿LigClient用接口,而不是实现类LigAgent。

2.3.2 创建 LigManager

我们创建两个方法。ConnectServer与DisconnectServer用来连接LigServer服务与断开LigServer服务。

采用ChannelFactory<T>来创建客户端通道同时获取客户端代理实例。看到红色的代码:

this.iLig.SayHelloToServer("LigManager Connecting : ClientHash : " + this.GetHashCode().ToString());

如果LigServer没有启动,ConnectServer会阻塞到这行代码,直到时间达到配置中的超时,会引发一个超时异常。

在WCF中。ChannelFactory<T>创建通道与服务端存在与否无关,也就是说,如果LigServer没有启动,ChannelFactory<T>创建通道也会成功,所以我们不能用创建通道成功与否来表明WCF连接是否已经成功建立,我们必须通过Client调用Server的服务来确保WCF已经连接。

WCF服务只有在客户端第一次调用服务的时候才会创建实例为客户端服务。我们为了确保LigServer已经启动,所以加入了SayHelloToServer代码去调用服务,如果调用成功,LigClient与LigServer才算正式建立成功。

然后加入配置,编写如下客户端代码就可以工作了

图 2.3.1 LigManager

2.3.3 创建Client

1)  我们采用LigManager中的静态资源来获取ILigAgent实例写日志。这样Client代码就变得很简单了。

2)  你可能注意到了,在这里我们并没有用ILigAgent的Initialize接口初始化Lig文件路径,而是用了系统默认路径。因为我要让不同的客户端去写同一个文件,而不是不同文件。
3)  以后的章节中我们会对ILigAgent进行改进,ILigAgent接口暴露的东西还是太多了,把WCF特性暴露了。

4)  同时使用ILigAgent也太过于复杂,因为使用LigClient我们自己还得创建一个LigManager,简简单单的写个日志,这样做使LigServer客户端的使用有些麻烦。别担心,在后面的章节中,你会看到,我们会解决这儿的所有问题,我们会让LigManager不复存在。

5)  写日志我们只需要这样 

ILigger lig= new Ligger(“ligfile”);
lig.Info(“YourInfo here”);

图 2.3.2 LigClient

图 2.3.3 LigClient 客户端配置

2.4 Lig系统测试

_________________________________________________________________________________

启动LigServer,同时启动4个LigClient,4个Client同时向默认文件Lig.lg中写入日志。。。

图 2.4.1 Lig系统测试

Lig系统已经工作

好了。到现在为止,这个经量级的Log已经完成。并且能够很好的稳定工作。

但到现在为止,它还不够优秀,表现在:

1)  我们还没有考虑,这个LigServer到底可以同时连接多少个LigClient。

2) 同样还有没考虑,如果LigClient如果出现异常怎么办。

3)  也没有解释LigServer控制台中出现的HashCode是什么东东

4)  LigServer与LigClient双向通信会是什么样子?服务端监控是什么样子?

在第三节中我们会解答这些所有的问题。。。

本节的源代码下载:

_________________________________________________________________________________

Litelog - WCF 项目应用连载[2] - 创建Lig日志系统 C# 源代码.rar

_________________________________________________________________________________

WCF 项目应用连载[3] - 双向通信 并发、实例管理与服务端监控

参考引文:
[1] Artech.WCF全面解析[M].2012
[2] O'Reilly.WCF编程[M].2009
[3] Adnrew Trolesen.C#与.net3.5/4高级程序设计[M].2009/2013

WCF 项目应用连载[2] - 创建Lig日志系统相关推荐

  1. WCF 项目应用连载[6] - 升级Lig服务 - 设计ILigger 构建一个完善的Lig版本

    前面我们已经搞定了对ChannelFactory与ServiceHost的扩展,形成了我们自己用的两个类: public class LWCF<T> public class LServi ...

  2. WCF 项目应用连载[11] - 结束

    这节,我们问答WCF项目应用连载第一节 WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序 提出的第一个问题:What is the WCF? 11.1 总结 ...

  3. WCF 项目应用连载[9] - 契约中的委托 事件参数处理

    这节是一节辅助内容..将说清楚Lig日志系统中是怎样使用事件参数与委托参数的. 1) WCF服务接口中不能直接使用委托参数. 2) WCF采用回调接口来实现双向通信,我们可以将WCF回调接口消息封装为 ...

  4. WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost - LServiceHost

    在升级Lig服务之前,我们先升级两个类,以满足我们对WCF自定义配置的需求. 4.1 扩展 ServiceHost的背景 _______________________________________ ...

  5. 【Java从0到架构师】交错的日志系统、SpringBoot 集成日志框架

    交错的日志系统.SpringBoot 集成日志框架 交错复杂的日志系统① - 多个项目实现 SLF4J 门面 交错复杂的日志系统② - 统一底层实现为 Logback 交错复杂的日志系统③ - 统一底 ...

  6. Unity自定义日志系统

    Unity的系统日志算是很好用,但当程序很大时,就会比较乱,所以在项目中我们往往要对日志系统进行重新封装使用. 一.日志系统封装 如下代码,我们可以通过m_Log来控制是否打印日志,或对输出的日志加入 ...

  7. C语言编写自己的日志系统

    文章目录 一.功能实现 二.日志源码 三.结果展示 在我们自己做项目过程中会用到日志系统来记录程序的信息,这就需要我们自己来完成日志系统. 一.功能实现 完成的主要功能: 日志文件位置可通过参数解析改 ...

  8. 基于sentry的前端错误监控日志系统(部署sentry服务器/前端项目部署)-让前端最快的定位到生产问题...

    背景 在这越来越发达的网络时代,web应用也是越来越复杂,尤其是前端的开发,也是越来越受重视. 所以在我们前端开发完成后,会有一些列的web应用的上线验证,如自测.QA测试.code review 等 ...

  9. 旧 WCF 项目迁移到 asp.net core + gRPC 的尝试

    一个月前,公司的运行WCF的windows服务器down掉了,由于 AWS 没有通知,没有能第一时间发现问题. 所以,客户提出将WCF服务由C#改为JAVA,在Linux上面运行:一方面,AWS对Li ...

最新文章

  1. B站一季度营收超预期,月活跃用户达1.72亿
  2. PHP扩展-扩展的生成和编译
  3. java从入门到精通_python精通后能赚多少?平均情况。普通智商,刚毕业朝九晚五工作,每天4到5小时学多久精通?...
  4. HDU - 5381 The sum of gcd(莫队/线段树区间合并)
  5. Redis:使用Redis的分布式锁
  6. 【Java】Java中的设计模式的介绍以及代码详解
  7. 【白皮书分享】低幼年龄段在线教育白皮书.pdf(附下载链接)
  8. 夸奖对方代码写的好_我写出这样干净的代码,老板直夸我
  9. 行测题库:行测每日一练常识判断练习题02.04
  10. php通用查询系统excel,Laravel+Excel通用查询填报系统
  11. 计算机改显存会有啥影响,显卡显存越大越好吗?显存对电脑速度的影响有哪些?...
  12. 2013-07-26 IT 要闻速记快想
  13. 计算机丢失uxthemedll,win10系统开机显示uxtheme.dll丢失的处理办法
  14. 腾讯云中间件读者敬启:2022年热门技术文章集锦,建议收藏
  15. fxsvr2.exe
  16. c语言stdlib和math区别,c 语言中,stdio 和stdlib有什么区别?各代表什么意思?
  17. 每个程序员都应该了解:KISS:60年前美国军方的编程原则。
  18. JVM 双亲委派模型
  19. 氮气咖啡会是未来的趋势吗?| 啡鸟集
  20. Qt phonon多媒体框架

热门文章

  1. 最全面鸿蒙系统开发的相关资料收录
  2. vue vuex和pinia(菠萝)的区别
  3. VMware虚拟机中摄像头打开显示黑屏或者摄像头打开无法弹出窗口的解决办法
  4. [源码解析] 模型并行分布式训练Megatron (5) --Pipedream Flush
  5. 机器人学导论(一)——空间描述和变换
  6. 网上学python靠谱吗?
  7. 云计算大数据学习中心作业2
  8. 大数据入门级学习攻略
  9. 软件工程-第五章-总体设计
  10. 【C语言】题目:输入某年某月某日,判断这一天是这一年的第几天?