十九、【.Net开源】EFW框架核心类库之WCF控制器

回《【开源】EFW框架系列文章索引

EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U

EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa

只有当你需要开发三层架构的系统并利用WCF作为系统的中间件,那么就需要使用WCF控制器。EFW框架中的Wcf控制器分为两个部分WcfClientController和WcfController,两者利用Wcf服务进行通讯,其中WcfClientController的功能与上章中的WinController控制器是一样的,而WcfController控制器就与WebController控制器类似实现客户端与后台逻辑的交互;WcfClientController是放在客户端中的与界面代码一个项目,而WcfController是放在后台WCF中间件中,这点我们一定要搞清楚,虽然安装包可以把所有程序集只打成一个,但是在程序运行的过程中客户端是不会执行后台的程序,而中间件也不会执行前台的程序,但是实体除外;实体在客户段只是作为一个数据结构使用,而在中间件除了可以当做数据结构,还能使用ORM中的相关操作;

本章主要内容通过解读框架源代码来学习WCF控制器是怎么实现的,以及学习控制器这种模式;还有就是框架中对于WCF服务使用仅仅只是为了实现客户端与服务端的通讯,并不会赞成把业务功能做成一个个服务提供给外部调用;然后把WCF通讯模块封装成了一个简单的WCF中间件程序;并且WCF中间件实现了路由器功能与负载均衡功能;

本文要点:

1.如何使用WCF控制器

2.WCF控制器的设计思路

3.控制器基类的BaseWCFClientController和BaseWCFController的实现

4.基于Json格式传递数据的JsonWCFController类的实现

5.自定义标签WCFControllerAttribute和WCFMethodAttribute的配置

6.客户端与服务端通讯WCF服务WCFHandlerService类的实现

WCF控制器源代码目录:

EFW框架控制器设计图:

1.如何使用WCF控制器

如上图,Book.Winform项目里包括界面文件frmBookManager.cs和WCF客户端控制器文件bookwcfclientController.cs,Books项目包括WCF控制器文件bookWcfController.cs,bookwcfclientController类继承框架中的BaseWCFClientController基类,bookWcfController类继承框架中的JsonWCFController基类。Books.Winform项目相当于WCF的客户端,Books项目就是WCF的服务端。

如上图,展示了bookwcfclientController客户端控制器与bookWcfController服务端控制器之间的调用关系;客户端执行保存书籍操作,通过InvokeWCFService方法访问服务端控制器,参数指定服务端控制器的名称bookWcfController和控制器的方法名称SaveBook,程序进入到服务端的bookWcfController对象并指定SaveBook方法中的逻辑代码保存数据到数据库;同样执行客户端获取书籍目录GetBook也是一样的过程,服务端GetBook返回的DataTable数据结构要转换为Json格式字符串传递到客户端,客户端接收Json数据再转换为DataTable绑定到界面上显示。

2.WCF控制器的设计思路

当初利用WCF技术设计三层架构的系统时,没想到是在控制器这层着手,想过在数据访问层做文章,把数据库操作对象oleDb封装成wcf服务,但是这样的话逻辑层代码等于要界面层代码一起,没有达到三层架构的目的,至少得逻辑层是在中间件上运行的;那么只得把把逻辑层封装成wcf服务,那必须把所有业务逻辑都进行一层包裹,开发的工作量不少,而且wcf服务多了部署起来又麻烦;后来想着WCF服务不能太多,一个就够了,而且逻辑层代码和界面层代码最好不需要更改,想着想着发现在控制器这层比较合适;把以前Winform版的控制器拆成两个部分客户端控制器和服务端控制器,客户端控制器的功能拥有Winform版控制器一样操作界面的职责,但不能调用逻辑层的代码的通过wcf服务访问服务端控制器,WCFHosting服务主机支撑着wcf服务端控制器的运行,对比web版系统WCFHosting服务主机相当于IIS,而wcf控制器相当于WebController控制器;所以这样一分析WCF系统就像Web版和Winform版的结合体,这样就让三种开发模式的各层代码达到最大化的重用,对比Winform版只需要改造一下控制器代码就由原来的二层架构变成了有中间件的三层模式;

Wcf客户端控制器必须继承框架中的BaseWCFClientController基类,wcf服务端控制器要继承JsonWCFController基类,而JsonWCFController又继承BaseWCFController基类;还有wcf服务器控制器类上需要指定自定义标签WCFControllerAttribute和WCFMethodAttribute;JsonWCFController类实现wcf服务利用Json格式进行数据传递,如果你觉得Json不适合可以自己扩展XMLWCFController或其他;WCFControllerAttribute和WCFMethodAttribute自定义标签标出系统中那些wcf控制器对象,这样客户端才能很方便的只要根据控制器名和方法名就可以访问控制器;

3.控制器基类的BaseWCFClientController和BaseWCFController的实现

框架中的源代码BaseWCFClientController基类的实现

BaseWCFClientController文件

  1 /// <summary>
  2     /// WCF控制器客户端基类
  3     /// </summary>
  4     public class BaseWCFClientController
  5     {
  6         private static readonly string myNamespace = "http://www.3yxx.com/";
  7         /// <summary>
  8         /// 客户端标识
  9         /// </summary>
 10         public string ClientID
 11         {
 12             get
 13             {
 14                 return EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("WCFClientID").ToString();
 15             }
 16         }
 17         /// <summary>
 18         /// wcf服务对象
 19         /// </summary>
 20         public IapiWCFHandlerService WCFService
 21         {
 22             get
 23             {
 24                  IapiWCFHandlerService _wcfService= EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("WCFService") as IapiWCFHandlerService;
 25                  if (WCFHeartbeat(_wcfService)==false)//|| ((System.ServiceModel.ClientBase<IapiWCFHandlerService>)(_wcfService)).State == CommunicationState.Faulted || ((System.ServiceModel.ClientBase<IapiWCFHandlerService>)(_wcfService)).State == CommunicationState.Closed)
 26                  {
 27                      //CreateWCFService(AppGlobal.cache.GetData("ClientService") as IClientService);
 28                      ReConnectionWCFService(AppGlobal.cache.GetData("ClientService") as IClientService);
 29                      _wcfService = EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("WCFService") as IapiWCFHandlerService;
 30                  }
 31                  return _wcfService;
 32             }
 33         }
 34
 35         /// <summary>
 36         /// 创建wcf服务
 37         /// </summary>
 38         /// <param name="mainfrm"></param>
 39         public static void CreateWCFService(IClientService mainfrm)
 40         {
 41             try
 42             {
 43                 NetTcpBinding binding = new NetTcpBinding("NetTcpBinding_WCFHandlerService");
 44                 //binding.OpenTimeout = TimeSpan.FromSeconds(10);
 45                 //binding.TransferMode = TransferMode.Buffered;
 46                 DuplexChannelFactory<IapiWCFHandlerService> mChannelFactory = new DuplexChannelFactory<IapiWCFHandlerService>(mainfrm, binding, System.Configuration.ConfigurationSettings.AppSettings["WCF_endpoint"]);
 47                 IapiWCFHandlerService wcfHandlerService = mChannelFactory.CreateChannel();
 48
 49                 string routerID;
 50                 string mProxyID;
 51                 using (var scope = new OperationContextScope(wcfHandlerService as IContextChannel))
 52                 {
 53                     // 注意namespace必须和ServiceContract中定义的namespace保持一致,默认是:http://tempuri.org
 54                     //var myNamespace = "http://www.3yxx.com/";
 55                     // 注意Header的名字中不能出现空格,因为要作为Xml节点名。
 56                     routerID = Guid.NewGuid().ToString();
 57                     var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, routerID);
 58                     OperationContext.Current.OutgoingMessageHeaders.Add(router);
 59                     mProxyID = wcfHandlerService.CreateDomain(GetLocalIPAddress());
 60                 }
 61
 62
 63                 if (AppGlobal.cache.Contains("WCFClientID")) AppGlobal.cache.Remove("WCFClientID");
 64                 if (AppGlobal.cache.Contains("WCFService")) AppGlobal.cache.Remove("WCFService");
 65                 if (AppGlobal.cache.Contains("ClientService")) AppGlobal.cache.Remove("ClientService");
 66                 if (AppGlobal.cache.Contains("routerID")) AppGlobal.cache.Remove("routerID");
 67
 68                 AppGlobal.cache.Add("WCFClientID", mProxyID);
 69                 AppGlobal.cache.Add("WCFService", wcfHandlerService);
 70                 AppGlobal.cache.Add("ClientService", mainfrm);
 71                 AppGlobal.cache.Add("routerID", routerID);
 72
 73                 //开启发送心跳
 74                 if (timer == null)
 75                     StartSendWCFHeartbeat();
 76                 else
 77                     timer.Start();
 78             }
 79             catch (Exception err)
 80             {
 81                 throw new Exception(err.Message);
 82             }
 83         }
 84         /// <summary>
 85         /// 重新连接wcf服务
 86         /// </summary>
 87         /// <param name="mainfrm"></param>
 88         public static void ReConnectionWCFService(IClientService mainfrm)
 89         {
 90             try
 91             {
 92                 NetTcpBinding binding = new NetTcpBinding("NetTcpBinding_WCFHandlerService");
 93                 //binding.OpenTimeout = TimeSpan.FromSeconds(10);
 94                 //binding.TransferMode = TransferMode.Buffered;
 95                 DuplexChannelFactory<IapiWCFHandlerService> mChannelFactory = new DuplexChannelFactory<IapiWCFHandlerService>(mainfrm, binding, System.Configuration.ConfigurationSettings.AppSettings["WCF_endpoint"]);
 96                 IapiWCFHandlerService wcfHandlerService = mChannelFactory.CreateChannel();
 97
 98                 using (var scope = new OperationContextScope(wcfHandlerService as IContextChannel))
 99                 {
100                     var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, AppGlobal.cache.GetData("routerID").ToString());
101                     OperationContext.Current.OutgoingMessageHeaders.Add(router);
102                     wcfHandlerService.ReConnection(AppGlobal.cache.GetData("WCFClientID").ToString());
103                 }
104
105                 if (AppGlobal.cache.Contains("WCFService")) AppGlobal.cache.Remove("WCFService");
106                 AppGlobal.cache.Add("WCFService", wcfHandlerService);
107
108                 //开启发送心跳
109                 if (timer == null)
110                     StartSendWCFHeartbeat();
111                 else
112                     timer.Start();
113             }
114             catch (Exception err)
115             {
116                 return;
117             }
118         }
119
120         //向服务端发送心跳,间隔时间为5s
121         static System.Timers.Timer timer;
122         static void StartSendWCFHeartbeat()
123         {
124             timer = new System.Timers.Timer();
125             timer.Interval = 5000;
126             timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
127             timer.Start();
128         }
129         static Object syncObj = new Object();////定义一个静态对象用于线程部份代码块的锁定,用于lock操作
130         static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
131         {
132             lock (syncObj)
133             {
134                 try
135                 {
136                     IapiWCFHandlerService _wcfService = EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("WCFService") as IapiWCFHandlerService;
137                     if (WCFHeartbeat(_wcfService) == false)
138                     {
139                         //CreateWCFService(AppGlobal.cache.GetData("ClientService") as IClientService);
140                         ReConnectionWCFService(AppGlobal.cache.GetData("ClientService") as IClientService);
141                     }
142                 }
143                 catch (Exception err)
144                 {
145
146                     throw new Exception(err.Message);
147                 }
148             }
149         }
150         static bool WCFHeartbeat(IapiWCFHandlerService _wcfService)
151         {
152             try
153             {
154                 using (var scope = new OperationContextScope(_wcfService as IContextChannel))
155                 {
156                     var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, AppGlobal.cache.GetData("routerID").ToString());
157                     OperationContext.Current.OutgoingMessageHeaders.Add(router);
158                     return _wcfService.Heartbeat(AppGlobal.cache.GetData("WCFClientID").ToString());
159                 }
160             }
161             catch (Exception err)
162             {
163                 timer.Stop();
164                 return false;
165             }
166         }
167         static string GetLocalIPAddress()
168         {
169             IPHostEntry IpEntry = Dns.GetHostEntry(Dns.GetHostName());
170             string myip = "";
171             foreach (IPAddress ip in IpEntry.AddressList)
172             {
173                 if (Regex.IsMatch(ip.ToString(), @"\d{0,3}\.\d{0,3}\.\d{0,3}\.\d{0,3}"))
174                 {
175                     myip = ip.ToString();
176                     break;
177                 }
178             }
179             return myip;
180         }
181
182         /// <summary>
183         /// 获取登录用户信息
184         /// </summary>
185         public SysLoginRight GetSysLoginRight
186         {
187             get
188             {
189                 if (EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser") != null)
190                 {
191                     return (SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser");
192                 }
193                 else
194                 {
195                     return new SysLoginRight();
196                 }
197             }
198         }
199
200         internal IBaseView _defaultView;
201         public IBaseView DefaultView
202         {
203             get { return _defaultView; }
204         }
205
206         private Dictionary<string, IBaseView> _iBaseView;
207         public Dictionary<string, IBaseView> iBaseView
208         {
209             get { return _iBaseView; }
210             set
211             {
212                 _iBaseView = value;
213                 foreach (KeyValuePair<string, IBaseView> val in _iBaseView)
214                 {
215                     //val.Value.ControllerEvent += new ControllerEventHandler(UI_ControllerEvent);
216                     val.Value.InvokeController = new ControllerEventHandler(UI_ControllerEvent);
217                 }
218             }
219         }
220
221         public CloseTab closeTab;
222
223         /// <summary>
224         /// 创建BaseWCFClientController的实例
225         /// </summary>
226         public BaseWCFClientController()
227         {
228
229         }
230         /// <summary>
231         /// 界面控制事件
232         /// </summary>
233         /// <param name="eventname">事件名称</param>
234         /// <param name="objs">参数数组</param>
235         /// <returns></returns>
236         public virtual object UI_ControllerEvent(string eventname, params object[] objs)
237         {
238
239
240             MethodInfo meth= this.GetType().GetMethod(eventname);
241             if (meth != null)
242             {
243
244                 return meth.Invoke(this, objs);
245             }
246
247             switch (eventname)
248             {
249                 case "Close":
250                     if (closeTab != null)
251                         closeTab();
252                     break;
253                 case "this":
254                     return this;
255                 default:
256                    break;
257             }
258
259             return null;
260         }
261
262         /// <summary>
263         /// 初始化全局web服务参数对象
264         /// </summary>
265         public virtual void Init() { }
266
267         public virtual IBaseView GetView(string frmName)
268         {
269             return iBaseView[frmName];
270         }
271
272         public virtual Object InvokeWCFService(string controller, string method, string jsondata)
273         {
274
275             string retJson;
276             using (var scope = new OperationContextScope(WCFService as IContextChannel))
277             {
278                 var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, AppGlobal.cache.GetData("routerID").ToString());
279                 OperationContext.Current.OutgoingMessageHeaders.Add(router);
280                 retJson = WCFService.ProcessRequest(ClientID, controller, method, jsondata);
281             }
282             object Result = JavaScriptConvert.DeserializeObject(retJson);
283             int ret = Convert.ToInt32(((Newtonsoft.Json.JavaScriptObject)(Result))["flag"]);
284             string msg = ((Newtonsoft.Json.JavaScriptObject)(Result))["msg"].ToString();
285             if (ret == 1)
286             {
287                 throw new Exception(msg);
288             }
289             else
290             {
291                 return ((Newtonsoft.Json.JavaScriptObject)(Result))["data"];
292             }
293         }
294
295         public virtual Object InvokeWCFService(string controller, string method, params object[] data)
296         {
297             //
298             string jsondata = JavaScriptConvert.SerializeObject(data, new AspNetDateTimeConverter());
299             return InvokeWCFService(controller, method, jsondata);
300         }
301
302
303         private object convertVal(Type t, object data)
304         {
305             object val = null;
306             if (t == typeof(Int32))
307                 val = Convert.ToInt32(data);
308             else if (t == typeof(DateTime))
309                 val = Convert.ToDateTime(data);
310             else if (t == typeof(Decimal))
311                 val = Convert.ToDecimal(data);
312             else if (t == typeof(Boolean))
313                 val = Convert.ToBoolean(data);
314             else if (t == typeof(String))
315                 val = Convert.ToString(data).Trim();
316             else if (t == typeof(Guid))
317                 val = new Guid(data.ToString());
318             else
319                 val = data;
320             return val;
321         }
322
323         public object[] ToArray(object data)
324         {
325             return (data as Newtonsoft.Json.JavaScriptArray).ToArray();
326         }
327         public List<T> ToListObj<T>(object data)
328         {
329             if (data is JavaScriptArray)
330             {
331                 PropertyInfo[] pros = typeof(T).GetProperties();
332                 List<T> list = new List<T>();
333                 for (int i = 0; i < (data as JavaScriptArray).Count; i++)
334                 {
335                     T obj = (T)Activator.CreateInstance(typeof(T));
336                     object _data = (data as JavaScriptArray)[i];
337                     for (int k = 0; k < pros.Length; k++)
338                     {
339                         object val = convertVal(pros[k].PropertyType, (_data as JavaScriptObject)[pros[k].Name]);
340                         pros[k].SetValue(obj, val, null);
341                     }
342                     list.Add(obj);
343                 }
344                 return list;
345             }
346
347             return null;
348         }
349         public DataTable ToDataTable(object data)
350         {
351             if (data is JavaScriptArray && (data as JavaScriptArray).Count>0)
352             {
353                 JavaScriptObject _data = (data as JavaScriptArray)[0] as JavaScriptObject;
354                 DataTable dt=new DataTable();
355                 foreach (var name in _data.Keys)
356                 {
357                     dt.Columns.Add(name, _data[name].GetType());
358                 }
359
360                 for (int i = 0; i < (data as JavaScriptArray).Count; i++)
361                 {
362                     object _jsarray = (data as JavaScriptArray)[i];
363                     DataRow dr= dt.NewRow();
364                     for (int k = 0; k < dt.Columns.Count; k++)
365                     {
366                         dr[k] = convertVal(dt.Columns[k].DataType, (_jsarray as JavaScriptObject)[dt.Columns[k].ColumnName]);
367                     }
368                     dt.Rows.Add(dr);
369                 }
370
371                 return dt;
372             }
373             return null;
374         }
375         public T ToObject<T>(object data)
376         {
377             T obj = (T)Activator.CreateInstance(typeof(T));
378             PropertyInfo[] pros = typeof(T).GetProperties();
379             for (int k = 0; k < pros.Length; k++)
380             {
381                 object val = convertVal(pros[k].PropertyType, (data as JavaScriptObject)[pros[k].Name]);
382                 pros[k].SetValue(obj, val, null);
383             }
384
385             return obj;
386         }
387
388     }

框架中的源代码BaseWCFController基类的实现

BaseWCFController文件

 1 /// <summary>
 2     /// WCF控制器服务端基类
 3     /// </summary>
 4     public class BaseWCFController : AbstractBusines
 5     {
 6         /// <summary>
 7         /// 数据库操作对象
 8         /// </summary>
 9         public AbstractDatabase oleDb
10         {
11             get
12             {
13                 return _oleDb;
14             }
15         }
16         /// <summary>
17         /// 当前客户端信息
18         /// </summary>
19         public WCFClientInfo ClientInfo
20         {
21             get;
22             set;
23         }
24         /// <summary>
25         /// 当前登录用户信息
26         /// </summary>
27         public SysLoginRight GetSysLoginRight
28         {
29             get
30             {
31                 if (ClientInfo != null && ClientInfo.LoginRight != null)
32                     return ClientInfo.LoginRight;
33                 return new SysLoginRight();
34             }
35         }
36
37         //public ViewEventHandler ViewHandler
38         //{
39         //    get { return RemoteLoaderController.ViewHandler; }
40         //}
41
42         /// <summary>
43         /// 客户端传递的参数
44         /// </summary>
45         public string ParamJsonData
46         {
47             get;
48             set;
49         }
50
51          /// <summary>
52         /// 创建BaseWCFController的实例
53         /// </summary>
54         public BaseWCFController()
55         {
56
57         }
58
59         /// <summary>
60         /// 初始化全局web服务参数对象
61         /// </summary>
62         public virtual void Init() { }
63     }

BaseWCFClientController基类封装的功能包括:

1)WCF服务对象,利用InvokeWCFService方法就可以调用服务端控制器

2)系统登录后的用户信息GetSysLoginRight,这样客户端控制器中就可以很方便的获取登录用户信息;

3)与Winform版控制器类似的对界面操作的iBaseView

4)将Json字符串转换为对象的方法

BaseWCFController基类封装的功能包括:

1)数据库操作对象oleDb

2)系统的当前登录用户信息GetSysLoginRight

4.基于Json格式传递数据的JsonWCFController类的实现

框架中的源代码JsonWCFController基类,实现数据结构转换为Json格式的字符串;用Json格式主要是觉得它是一种轻量级的数据交换格式,还有就是和web版的保持一致;

JsonWCFController文件

  1 /// <summary>
  2     /// 基于Json格式的WCF服务基类
  3     /// </summary>
  4     public class JsonWCFController : BaseWCFController, IToJson, EFWCoreLib.WCFHandler.IJsonToObject
  5     {
  6         #region  值转换
  7         private object convertVal(Type t, object data)
  8         {
  9             object val = null;
 10             if (t == typeof(Int32))
 11                 val = Convert.ToInt32(data);
 12             else if (t == typeof(DateTime))
 13                 val = Convert.ToDateTime(data);
 14             else if (t == typeof(Decimal))
 15                 val = Convert.ToDecimal(data);
 16             else if (t == typeof(Boolean))
 17                 val = Convert.ToBoolean(data);
 18             else if (t == typeof(String))
 19                 val = Convert.ToString(data).Trim();
 20             else if (t == typeof(Guid))
 21                 val = new Guid(data.ToString());
 22             else
 23                 val = data;
 24             return val;
 25         }
 26         #endregion
 27
 28         #region IToJson 成员
 29
 30         public string ToJson(object model)
 31         {
 32             string value = JavaScriptConvert.SerializeObject(model, new AspNetDateTimeConverter());
 33             return value;
 34         }
 35
 36         public string ToJson(System.Data.DataTable dt)
 37         {
 38             string value = JavaScriptConvert.SerializeObject(dt);
 39             return value;
 40         }
 41
 42         public string ToJson(params object[] data)
 43         {
 44             string value = JavaScriptConvert.SerializeObject(data, new AspNetDateTimeConverter());
 45             return value;
 46         }
 47
 48         #endregion
 49
 50         #region IJsonToObject成员
 51         public T ToObject<T>(string json)
 52         {
 53             return JavaScriptConvert.DeserializeObject<T>(json);
 54         }
 55
 56         public object ToObject(string json)
 57         {
 58             return JavaScriptConvert.DeserializeObject(json);
 59         }
 60
 61         public object[] ToArray(object data)
 62         {
 63             return (data as Newtonsoft.Json.JavaScriptArray).ToArray();
 64         }
 65
 66         public List<T> ToListObj<T>(object data)
 67         {
 68             if (data is JavaScriptArray)
 69             {
 70                 PropertyInfo[] pros = typeof(T).GetProperties();
 71                 List<T> list = new List<T>();
 72                 for (int i = 0; i < (data as JavaScriptArray).Count; i++)
 73                 {
 74                     T obj = (T)Activator.CreateInstance(typeof(T));
 75                     object _data = (data as JavaScriptArray)[i];
 76                     for (int k = 0; k < pros.Length; k++)
 77                     {
 78                         object val = convertVal(pros[k].PropertyType, (_data as JavaScriptObject)[pros[k].Name]);
 79                         pros[k].SetValue(obj, val, null);
 80                     }
 81                     list.Add(obj);
 82                 }
 83                 return list;
 84             }
 85
 86             return null;
 87         }
 88
 89         public DataTable ToDataTable(object data)
 90         {
 91             if (data is JavaScriptArray && (data as JavaScriptArray).Count > 0)
 92             {
 93                 JavaScriptObject _data = (data as JavaScriptArray)[0] as JavaScriptObject;
 94                 DataTable dt = new DataTable();
 95                 foreach (var name in _data.Keys)
 96                 {
 97                     dt.Columns.Add(name, _data[name].GetType());
 98                 }
 99
100                 for (int i = 0; i < (data as JavaScriptArray).Count; i++)
101                 {
102                     object _jsarray = (data as JavaScriptArray)[i];
103                     DataRow dr = dt.NewRow();
104                     for (int k = 0; k < dt.Columns.Count; k++)
105                     {
106                         dr[k] = convertVal(dt.Columns[k].DataType, (_jsarray as JavaScriptObject)[dt.Columns[k].ColumnName]);
107                     }
108                     dt.Rows.Add(dr);
109                 }
110
111                 return dt;
112             }
113             return null;
114         }
115
116         public T ToObject<T>(object data)
117         {
118             T obj = (T)Activator.CreateInstance(typeof(T));
119             PropertyInfo[] pros = typeof(T).GetProperties();
120             for (int k = 0; k < pros.Length; k++)
121             {
122                 object val = convertVal(pros[k].PropertyType, (data as JavaScriptObject)[pros[k].Name]);
123                 pros[k].SetValue(obj, val, null);
124             }
125
126             return obj;
127         }
128         #endregion
129     }

5.自定义标签WCFControllerAttribute和WCFMethodAttribute的配置

配置WCFControllerAttribute和WCFMethodAttribute标签的目的就是减少暴露给客户端的对象,只有指定了标签的对象才能被客户端所调用;而且让客户端调用的方式更简单,只需指定控制器的名称和方法名就行了;所以后台代码不能有相同名称的控制器对象,如果指定相同的控制器名称那么识别不了;

WCFControllerAttribute文件

 1 /// <summary>
 2     /// WCF服务对象自定义标签
 3     /// </summary>
 4     [AttributeUsageAttribute(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
 5     public class WCFControllerAttribute : Attribute
 6     {
 7         string _memo;
 8         public string Memo
 9         {
10             get { return _memo; }
11             set { _memo = value; }
12         }
13     }

WCFMethodAttribute文件

 1  [AttributeUsageAttribute(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
 2     public class WCFMethodAttribute : Attribute
 3     {
 4         private string _openDBNames;
 5         /// <summary>
 6         /// 打开数据库,中间用,号隔开
 7         /// </summary>
 8         public string OpenDBKeys
 9         {
10             get { return _openDBNames; }
11             set { _openDBNames = value; }
12         }
13         private string _memo;
14         public string Memo
15         {
16             get { return _memo; }
17             set { _memo = value; }
18         }
19     }

6.客户端与服务端通讯WCF服务WCFHandlerService类的实现

客户端与服务端是利用wcf服务进行通信的,而WCFHandlerService类就是实现的WCF服务对象,WCFHandlerService对象实现调用wcf服务端控制器的操作契约就是ProcessRequest方法,本章先讲解一下此核心方法,其他的功能在后面讲WcfHosting服务主机的时候会详细讲解;

WCFHandlerService文件

 1 public string ProcessRequest(string mProxyID, string controller, string method, string jsondata)
 2         {
 3             try
 4             {
 5                 if (Convert.ToInt32(HostSettingConfig.GetValue("debug")) == 1)
 6                     Loader.ShowHostMsg(DateTime.Now, "客户端[" + mProxyID + "]正在执行:" + controller + "." + method + "(" + jsondata + ")");
 7                 string retJson = Loader.ProcessRequest(mProxyID, controller, method, jsondata);
 8                 return "{\"flag\":0,\"msg\":" + "\"\"" + ",\"data\":" + retJson + "}";
 9             }
10             catch (Exception err)
11             {
12                 if (err.InnerException == null)
13                 {
14                     Loader.ShowHostMsg(DateTime.Now, "客户端[" + mProxyID + "]执行失败:" + controller + "." + method + "(" + jsondata + ")\n错误原因:" + err.Message);
15                     return "{\"flag\":1,\"msg\":" + "\"" + err.Message + "\"" + "}";
16                 }
17                 else
18                 {
19                     Loader.ShowHostMsg(DateTime.Now, "客户端[" + mProxyID + "]执行失败:" + controller + "." + method + "(" + jsondata + ")\n错误原因:" + err.InnerException.Message);
20                     return "{\"flag\":1,\"msg\":" + "\"" + err.InnerException.Message + "\"" + "}";
21                 }
22             }
23         }

时间: 2024-10-23 15:52:05

十九、【.Net开源】EFW框架核心类库之WCF控制器的相关文章

十七、EnterpriseFrameWork框架核心类库之Web控制器

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WebController就是解决JqueryEasyUI与逻辑层的交互,之间的数据是通过Json字符串来传递:值得注意的是WebController的代码一定不要和EFWWeb项目放在一起,你可以单独建一个项目类库,也可以和逻辑层项目放一起:在EFWWeb项目不要编写任何C#代码,这个在前面的文章中就提过,可以让你的Web项

二十、【.Net开源】EFW框架核心类库之WebService服务

回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa EFW框架中的WebService服务开发方式与传统的net项目中开发不太一样,传统的开发方式虽然也挺简单但在后面的发布部署还是挺麻烦的,而在EFW框架中开发Webservice就跟编写普通的C#代码一样,并不需要单独建WebService服务项目,不需要Asmx文件:所以发

十八、EnterpriseFrameWork框架核心类库之Winform控制器

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WinController控制器可以说是整个Winform版中最具有价值的地方,能够熟练使用它的话,可以让你写得代码结构清晰不知多少倍,真正的做到了CS开发的界面层与逻辑层的完全隔离:更重要的是改变了你写界面代码的思维,让你一次性写出功能完善的代码,真的,传统的那种事件驱动的方式编码会让你的代码变得越来越臃肿,就算你懂得不断重

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服

十六、【适合中小企业的.Net轻量级开源框架】EnterpriseFrameWork框架核心类库之单点登录SSO

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 如上图,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录:根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返

十二、EnterpriseFrameWork框架核心类库之与EntLib结合

从本章开始对框架的讲叙开始进入核心类库的讲解,前面都是对框架外在功能讲解,让人有个整体的概念,知道包含哪些功能与对系统开发有什么帮助.以后多章都是讲解核心类库的,讲解的方式基本按照代码的目录结构,这样阅读代码的时候也可以针对性看:还有就是为了更好理解文章中的内容把目前还不够完善的源代码发布,这个版本Winform部分基本可以直接运行,而Web部分与WCF部分的控制器代码没有完成,所以暂时还运行不起来,不过这并不影响学习核心类库,再就是尽快在下个版本发布一个完整版本给大家: EnterpriseF

十五、EnterpriseFrameWork框架核心类库之系统启动入口与初始化

本章内容是讲三种开发模式,web模式.Winform模式和Wcf模式的系统启动入口有什么区别,以及启动后系统初始化的内容:为什么要把这些单独提出来讲一章,因为我觉得本章非常重要,我们都知道程序中的main()函数,称之为主函数,是所有程序运行的入口:当你拿着一个程序肯定是从这个函数开始阅读,慢慢的深入了解整个程序的运行流程:而光看那些功能代码块是掌握不了系统运行时的一些机制的: 只有掌握本章的内容后,那么在以后项目中遇到的问题基本上都能直接定位,并找到产生的原因,不然你会觉得所有产生的问题都莫名

十四、EnterpriseFrameWork框架核心类库之简易ORM

在写本章前先去网上找了一下关于ORM的相关资料,以为本章做准备,发现很多东西今天才了解,所以在这里也对ORM做不了太深入的分析,但还是浅谈一下EFW框架中的设计的简易ORM:文中有一点讲得很有道理,Dao与ORM的区别,Dao是对数据库操作的封装,编写的代码方式像一种设计方法,而ORM支持对象与数据结构的映射,更像一种代码开发工具,有了这个工具会让我们开发代码更简单方便:但是同一类工具有简单的也有复杂的,比如文字工具有简单的Notepad,也有复杂的Word,不是说有了复杂的简单的工具就不需要了

【开源EFW框架】框架中自定义控件GridBoxCard使用实例说明

回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://pan.baidu.com/s/1eQCc69G 在<二十五.EFW框架Winform前端开发之自定义控件>中列出了EFW框架中的强大自定义控件及每个控件的API说明,但是对如何使用这些控件还不是很明白,本章通过实例的方式详细说明GridBoxCard控件的使用方法: 本文要点: 1.实例功能说明