架构搭建----基于DDD领域驱动设计的WCF+EF+WPF分层框架(2)

写在最前面:转载请注明出处

目录置顶:

架构搭建

架构是基于DDD领域驱动模型的,DDD的思想我就不介绍了,园里有挺多的介绍了,另外在下面的架构图里面也会有体现,架构图本应该用UML图展示一下的,我觉得麻烦,我直接把我的项目截一个图介绍一下:

项目我分了四个解决方案文件夹:ACS.OA.Common、ACS.OA.UIClient、ACS.OA.WCFServer、ACS.OA.WebSite(这个本次博客不打算介绍,直接忽略)。

ACS.OA.Common

这个文件夹里面我建了Base、Global、Model、WCFContract四个项目,这四个项目大家看名称就知道作用了。

Base的内部结构我也截一张图吧

这个重点在CS文件夹里面,Cache缓存类,Communication通讯类,CustomException 异常处理类,Lib帮助集合(比较多,我把截图放旁边了),Log日志类(Log4Net)

我重点讲一下通讯类Pactet数据包

 1    /// <summary>
 2    /// 打包、解包
 3    /// </summary>
 4    /// <typeparam name="T">数据类型 object</typeparam>
 5     public abstract class Packet<T>
 6     {
 7         /// <summary>
 8         /// 打包数据
 9         /// </summary>
10         /// <param name="t"></param>
11         /// <param name="strKey">加密Key</param>
12         /// <returns></returns>
13         public static byte[] PacketData(T t, string strKey)
14         {
15             var jSetting = new JsonSerializerSettings();
16             jSetting.NullValueHandling = NullValueHandling.Ignore;      //忽略为NULL的值
17
18             byte[] bytContent;
19             string strJson = JsonConvert.SerializeObject(t, jSetting);  //T转Json
20             strJson = DESHelper.Encrypt(strJson, strKey);               //加密
21             bytContent = SerializeHelper.Serialize(strJson);            //压缩转byte[]
22
23             Init(bytContent);
24             return bytContent;
25         }
26
27         /// <summary>
28         /// 解包数据
29         /// </summary>
30         /// <param name="bytContent"></param>
31         /// <param name="strKey">解密Key</param>
32         /// <returns></returns>
33         public static T DePacketData(byte[] bytContent, string strKey)
34         {
35             var jSetting = new JsonSerializerSettings();
36             jSetting.NullValueHandling = NullValueHandling.Ignore;                       //忽略为NULL的值
37
38             T t;
39             string strJson = SerializeHelper.Deserialize(bytContent).ToString();         //解压缩转string
40             strJson = DESHelper.Decrypt(strJson, strKey);                                //解密
41             t = (T)JsonConvert.DeserializeObject(strJson, typeof(T), jSetting);           //Json转T
42             return t;
43         }
44
45     }

里面的DESHelper的加密解密方法用的是TripleDESCryptoServiceProvider,需要的话自己引用一下就可以自己写了,这个实例比较多,我就不贴代码了。

我说一下我为何这么做的原因

打包步骤:

我先把实体类转为Json字符串目的为统一传输规则,这样做不用考虑发送方和接收方是什么语言开发的,接收方收到json解析就行了。

我又把Json串加密,这是为了安全考虑,数据传输用明文不安全吧。

转byte[] 压缩一下,文件会小很多,考虑的是传输效率。

解包步骤 就是打包的逆向了,不解释了啊。

Lib帮助类集合里面,我讲一下WCFHandler类,先贴代码

  1     public class WCFHandler
  2     {
  3         public static T CreateHttpServiceClient<T>(string webAddress, string serviceName)
  4         {
  5             T t = default(T);
  6             object obj = Activator.CreateInstance(typeof(T), new object[]
  7             {
  8                 GetHttpBinding(),
  9                 GetEndpoint(webAddress, serviceName)
 10             });
 11             t = (T)(obj);
 12             return t;
 13         }
 14
 15         public static T CreateTcpServiceClient<T>(string webAddress, string serviceName, bool isStream=false)
 16         {
 17             T t = default(T);
 18             object obj;
 19             if (isStream) //流传输
 20             {
 21                 obj = Activator.CreateInstance(typeof(T), new object[]
 22                 {
 23                     GetFileTcpBinding(),
 24                     GetEndpoint(webAddress, serviceName)
 25                 });
 26             }
 27             else         //缓存传输
 28             {
 29                 obj = Activator.CreateInstance(typeof(T), new object[]
 30                 {
 31                     GetTcpBinding(),
 32                     GetEndpoint(webAddress, serviceName)
 33                 });
 34             }
 35             t = (T)(obj);
 36             return t;
 37         }
 38
 39         public static NetTcpBinding GetTcpBinding()
 40         {
 41             return new NetTcpBinding
 42             {
 43                 MaxBufferPoolSize = 2147483646L,
 44                 MaxReceivedMessageSize = 2147483646L,
 45                 CloseTimeout = new TimeSpan(0, 0, 10),
 46                 OpenTimeout = new TimeSpan(0, 0, 10),
 47                 ReceiveTimeout = TimeSpan.MaxValue,
 48                 SendTimeout = new TimeSpan(0, 20, 0),
 49                 ReaderQuotas =
 50                 {
 51                     MaxDepth=64,
 52                     MaxStringContentLength=2147483646,
 53                     MaxArrayLength=2147483646,
 54                     MaxBytesPerRead=2147483646,
 55                     MaxNameTableCharCount=2147483646
 56                 },
 57                 ReliableSession =
 58                 {
 59                     Enabled = true,
 60                     Ordered = true,
 61                     InactivityTimeout = new TimeSpan(0, 0, 10)
 62                 },
 63                 Security =
 64                 {
 65                     Mode=SecurityMode.None,
 66                     Message =
 67                     {
 68                         ClientCredentialType = System.ServiceModel.MessageCredentialType.Windows
 69                     },
 70                     Transport =
 71                     {
 72                         ClientCredentialType =  TcpClientCredentialType.Windows
 73                     }
 74                 },
 75
 76             };
 77         }
 78
 79
 80         /// <summary>
 81         /// TCP大文件断点续传
 82         /// </summary>
 83         /// <returns></returns>
 84         public static NetTcpBinding GetFileTcpBinding()
 85         {
 86             return new NetTcpBinding
 87             {
 88                 MaxBufferPoolSize = 2147483646L,
 89                 MaxReceivedMessageSize = 2147483646L,
 90                 CloseTimeout = new TimeSpan(0, 0, 10),
 91                 OpenTimeout = new TimeSpan(0, 0, 10),
 92                 ReceiveTimeout = TimeSpan.MaxValue,
 93                 SendTimeout = new TimeSpan(0, 20, 0),
 94                 TransferMode=TransferMode.Streamed,
 95                 ReaderQuotas =
 96                 {
 97                     MaxDepth=64,
 98                     MaxStringContentLength=2147483646,
 99                     MaxArrayLength=2147483646,
100                     MaxBytesPerRead=2147483646,
101                     MaxNameTableCharCount=2147483646
102                 },
103                 //ReliableSession =
104                 //{
105                 //    Enabled = true,
106                 //    Ordered = true,
107                 //    InactivityTimeout = new TimeSpan(1, 0, 0)
108                 //},
109                 //Security =
110                 //{
111                 //    Mode=SecurityMode.None,
112                 //    Message =
113                 //    {
114                 //        ClientCredentialType = System.ServiceModel.MessageCredentialType.Windows
115                 //    },
116                 //    Transport =
117                 //    {
118                 //        ClientCredentialType =  TcpClientCredentialType.Windows
119                 //    }
120                 //},
121
122             };
123         }
124
125         public static WSHttpBinding GetHttpBinding()
126         {
127             return new WSHttpBinding
128             {
129                 MaxBufferPoolSize = 2147483646L,
130                 MaxReceivedMessageSize = 2147483646L,
131                 CloseTimeout = new TimeSpan(0, 0, 10),
132                 OpenTimeout = new TimeSpan(0, 0, 10),
133                 ReceiveTimeout = new TimeSpan(0, 20, 0),
134                 SendTimeout = new TimeSpan(0, 20, 0),
135                 ReliableSession =
136                 {
137                     Enabled = true,
138                     Ordered = true,
139                     InactivityTimeout = new TimeSpan(0, 0, 10)
140                 },
141                 UseDefaultWebProxy = false,
142                 Security =
143                 {
144                     Mode = SecurityMode.None,
145                     Message =
146                     {
147                         ClientCredentialType = System.ServiceModel.MessageCredentialType.Windows
148                     },
149                     Transport =
150                     {
151                         ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows
152                     }
153                 },
154             };
155         }
156         public static EndpointAddress GetEndpoint(string webAddress, string serviceName)
157         {
158             Uri uri = new Uri(webAddress + "/" + serviceName + ".svc");
159             return new EndpointAddress(uri, new AddressHeader[0]);
160         }
161
162         public static EndpointAddress GetIMEndpoint(string webAddress, string serviceName)
163         {
164             Uri uri = new Uri(webAddress + "/" + serviceName + ".svc");
165             return new EndpointAddress(uri, new AddressHeader[0]);
166         }
167     }

这个里面是NET.TCP 和WSHttp 的WCF配置,这个类主要用于客户端的 需要传入两个参数“webAddress”,“serviceName”

webaddress我的做法是配置在客户端的App.Config读取。

serviceName我是根据每一个不同方法手工写入的

我再贴一下用法实例

 1        /// <summary>
 2         /// 艾克仕网络云OA企业名片
 3         /// </summary>
 4         public FirmCardPacket GetFirmCard(FirmCardPacket packet)
 5         {
 6             using (SettingServiceClient client = CreateTcpServiceClient<SettingServiceClient>(Caches.GolbalCache.WCFAddressCache, "MainClient/SettingService"))
 7             {
 8                 client.Open();
 9                 byte[] bt = null;
10                 bt = Packet<FirmCardPacket>.PacketData(packet, strKey);
11                 bt = client.GetFirmCard(bt);
12                 packet = Packet<FirmCardPacket>.DePacketData(bt, strKey);
13                 client.Close();
14             }
15             return packet;
16         }

这个现在就展示一下用法,到我把WCF代理讲完,在UI里面我详细讲。



Base主要的是这些了,下面讲Global

先贴图

Global项目就是它的字面意思,全局的信息或者配置就放在这里。这个不用多讲了,大家如果使用我这套架构的话,如何划分全局还得靠自己,每个项目一般都不一样的。



下面是Model

Model我的文件夹分类规则是一个客户端项目对应一个Model文件夹,多个客户端公用的在Common文件夹,Base文件夹是基类举一个例子说明基类的用法

WPF需要实时刷新界面数据的话,我的实体如IMinfo就会继承Notify。IMpacket是具体的数据包需要继承PacketModel。

PacketModel里面是一些公共属性,LoginId,FirmId,ResultCode,ResultMsg 这些信息。

我贴一下Notify的代码

 1 public abstract class Notify : INotifyPropertyChanged
 2     {
 3         public event PropertyChangedEventHandler PropertyChanged;
 4
 5         protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
 6         {
 7             if (object.Equals(storage, value)) return false;
 8
 9             storage = value;
10             this.OnPropertyChanged(propertyName);
11
12             return true;
13         }
14
15         protected void OnPropertyChanged(string propertyName)
16         {
17             var eventHandler = this.PropertyChanged;
18             if (eventHandler != null)
19             {
20                 eventHandler(this, new PropertyChangedEventArgs(propertyName));
21             }
22         }
23     }

这个代码不解释了,做WPF的都知道。



ACS.OA.WCFContract

WCF契约,我为何要写在这里呢?是因为我是使用SvcUtil生成的WCF代理类,这个代理类和WCF服务库都公用这个契约,代理类和服务库的代码就会很简洁了,而且可以保证代理类和服务库的方法一致。

契约不用贴图,WCF有明确规定的,等到即时通讯需要双工的地方我会贴特定的契约接口。

到此,ACS.OA.Common解决方案文件夹讲完,下面讲ACS.OA.WCFServer,不要走开,精彩还在后面

ACS.OA.WCFServer

<p><span style="font-size: 16px;"><strong><span style="color: #ff0000;"><a href="http://www.cnblogs.com/acssoft/p/5370286.html"><span style="color: #ff0000;">写在最前面:转载请注明出处</span></a></span></strong></span></p>

时间: 2024-10-14 09:04:21

架构搭建----基于DDD领域驱动设计的WCF+EF+WPF分层框架(2)的相关文章

WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4)

写在最前面:转载请注明出处 目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DD

基于DDD领域驱动设计的WCF+EF+WPF分层框架

目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DDD领域驱动设计的WCF+EF

WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3)

写在最前面:转载请注明出处 目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DD

(转载)浅谈我对DDD领域驱动设计的理解

原文地址:http://www.cnblogs.com/netfocus/p/5548025.html 从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品.所以,自然而然就想到要做一个普通电商系统,用于实现在线销售自己企业产品的目的. 再比如,我是一家互联网公司,公司有很多系统对外提供服务,面向很多客户端设备.但是最近由于各种原因,导致服务经常出故

DDD领域驱动设计仓储Repository

DDD领域驱动设计初探(二):仓储Repository(上) 前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repository,为什么Repository会有这么大的争议,博主认为主要原因无非以下两点:一是Repository的真实意图没有理解清楚,导致设计的紊乱,随着项目的横向和纵向扩展,到最后越来越难维护:二是赶时髦的为了“模式”而“模式”,仓储并非适用于所有项目,这就像没有任何一种架构能解决所有的设计难题一样.本篇

浅谈我对DDD领域驱动设计的理解

从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品.所以,自然而然就想到要做一个普通电商系统,用于实现在线销售自己企业产品的目的. 再比如,我是一家互联网公司,公司有很多系统对外提供服务,面向很多客户端设备.但是最近由于各种原因,导致服务经常出故障.所以,我们希望通过各种措施提高服务的质量和稳定性.其中的一个措施就是希望能做一个灰度发布的平台,这个

C#进阶系列——DDD领域驱动设计初探(六):领域服务

前言:之前一直在搭建项目架构的代码,有点偏离我们的主题(DDD)了,这篇我们继续来聊聊DDD里面另一个比较重要的知识点:领域服务.关于领域服务的使用,书中也介绍得比较晦涩,在此就根据博主自己的理解谈谈这个知识点的使用. DDD领域驱动设计初探系列文章: C#进阶系列——DDD领域驱动设计初探(一):聚合 C#进阶系列——DDD领域驱动设计初探(二):仓储Repository(上) C#进阶系列——DDD领域驱动设计初探(三):仓储Repository(下) C#进阶系列——DDD领域驱动设计初探

C#进阶系列——DDD领域驱动设计初探(二):仓储Repository(上)

前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repository,为什么Repository会有这么大的争议,博主认为主要原因无非以下两点:一是Repository的真实意图没有理解清楚,导致设计的紊乱,随着项目的横向和纵向扩展,到最后越来越难维护:二是赶时髦的为了“模式”而“模式”,仓储并非适用于所有项目,这就像没有任何一种架构能解决所有的设计难题一样.本篇通过这个设计的Demo来谈谈博主对仓储的理解,有不对的地方还望

DDD领域驱动设计初探(一):聚合

前言:又有差不多半个月没写点什么了,感觉这样很对不起自己似的.今天看到一篇博文里面写道:越是忙人越有时间写博客.呵呵,似乎有点道理,博主为了证明自己也是忙人,这不就来学习下DDD这么一个听上去高大上的东西.前面介绍了下MEF和AOP的相关知识,后面打算分享Automapper.仓储模式.WCF等东西的,可是每次准备动手写点什么的时候,就被要写的Demo难住了,比如仓储模式,使用过它的朋友应该知道,如果你的项目不是按照DDD的架构而引入仓储的设计,那么会让它变得很“鸡肋”,用不好就会十分痛苦,之前