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

十九、【.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                 else112                     timer.Start();113             }114             catch (Exception err)115             {116                 return;117             }118         }119 120         //向服务端发送心跳,间隔时间为5s121         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                 try135                 {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             try153             {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 GetSysLoginRight186         {187             get188             {189                 if (EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser") != null)190                 {191                     return (SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser");192                 }193                 else194                 {195                     return new SysLoginRight();196                 }197             }198         }199 200         internal IBaseView _defaultView;201         public IBaseView DefaultView202         {203             get { return _defaultView; }204         }205 206         private Dictionary<string, IBaseView> _iBaseView;207         public Dictionary<string, IBaseView> iBaseView208         {209             get { return _iBaseView; }210             set211             {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             else290             {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 = http://www.mamicode.com/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             else319                 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 = http://www.mamicode.com/(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 = http://www.mamicode.com/(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     }
View Code

 

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

BaseWCFController文件

 1 /// <summary> 2     /// WCF控制器服务端基类 3     /// </summary> 4     public class BaseWCFController : AbstractBusines 5     { 6         /// <summary> 7         /// 数据库操作对象 8         /// </summary> 9         public AbstractDatabase oleDb10         {11             get12             {13                 return _oleDb;14             }15         }16         /// <summary>17         /// 当前客户端信息18         /// </summary>19         public WCFClientInfo ClientInfo20         {21             get;22             set;23         }24         /// <summary>25         /// 当前登录用户信息26         /// </summary>27         public SysLoginRight GetSysLoginRight28         {29             get30             {31                 if (ClientInfo != null && ClientInfo.LoginRight != null)32                     return ClientInfo.LoginRight;33                 return new SysLoginRight();34             }35         }36 37         //public ViewEventHandler ViewHandler38         //{39         //    get { return RemoteLoaderController.ViewHandler; }40         //}41 42         /// <summary>43         /// 客户端传递的参数44         /// </summary>45         public string ParamJsonData46         {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     }
View Code

 

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 = http://www.mamicode.com/JavaScriptConvert.SerializeObject(model, new AspNetDateTimeConverter()); 33             return value; 34         } 35  36         public string ToJson(System.Data.DataTable dt) 37         { 38             string value =http://www.mamicode.com/ JavaScriptConvert.SerializeObject(dt); 39             return value; 40         } 41  42         public string ToJson(params object[] data) 43         { 44             string value = http://www.mamicode.com/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 = http://www.mamicode.com/(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 = http://www.mamicode.com/(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         #endregion129     }
View Code

 

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     }
View Code

 

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 Memo15         {16             get { return _memo; }17             set { _memo = value; }18         }19     }
View Code

 

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                 else18                 {19                     Loader.ShowHostMsg(DateTime.Now, "客户端[" + mProxyID + "]执行失败:" + controller + "." + method + "(" + jsondata + ")\n错误原因:" + err.InnerException.Message);20                     return "{\"flag\":1,\"msg\":" + "\"" + err.InnerException.Message + "\"" + "}";21                 }22             }23         }
View Code

 

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