对于WCF的宿主启动来说,有好多方法,单独启动也很简单,可以根据业务需要来自由选择(单独启动方法这里就不做解释)
对于业务服务比较多的时候,往往需要多个服务来承载系统,但是如果将服务启动单独写代码启动的话,这样就造成代码的耦合,增加服务,删除服务都需要对宿主程序进行修改编译,因而就需要一个批量启动的办法
现在着重整理一下理由反射批量启动
思路:1、自定义两个属性,用于接口和实现类,一个为接口属性,一个为实现类属性
2、利用反射获取指定程序集的所有类文件,根据标记属性可以获取到那些为WCF接口和那些为WCF实现类
3、可以通过反射获取到实现类继承与什么接口
4、根据前三项即可将指定程序集的接口类和实现类对应
具体代码如下:
属性:
1 namespace ESTM.WCF.Service 2 { 3 //标记此特性的为WCF服务接口 4 public class ServiceInterfaceAttribute : Attribute 5 { 6 } 7 8 //标记此特性的为WCF服务接口实现类 9 public class ServiceClassAttribute : Attribute 10 { 11 } 12 }
接口和实现
1 namespace ESTM.WCF.Service 2 { 3 /// <summary> 4 /// 工厂布局模块接口契约 5 /// </summary> 6 [ServiceInterface] 7 [ServiceContract] 8 public interface IFactoryLayoutWCFService 9 { 10 [OperationContract] 11 List<DTO_TM_PLANT> GetAllPlant(); 12 } 13 }
1 namespace ESTM.WCF.Service 2 { 3 [ServiceClass] 4 public class FactoryLayoutWCFService : IFactoryLayoutWCFService 5 { 6 public List<DTO_TM_PLANT> GetAllPlant() 7 { 8 throw new NotImplementedException(); 9 } 10 } 11 }
WCF 批量启动帮助类
1 namespace ESTM.WCF.Service 2 { 3 public class Bootstrapper 4 { 5 private string strBaseServiceUrl = ConfigurationManager.AppSettings["ServiceUrl"].ToString(); 6 7 //启动所有的服务 8 public void StartServices() 9 { 10 //1.读取此程序集里面的有服务契约的接口和实现类 11 var assembly = Assembly.Load(typeof(Bootstrapper).Namespace); 12 //获取当前程序集的所有类文件(包括接口和类) 13 var lstType = assembly.GetTypes(); 14 //存储当前程序集的所有接口 15 var lstTypeInterface = new List<Type>(); 16 //存储当前程序集的所有接口实现类 17 var lstTypeClass = new List<Type>(); 18 19 foreach (var oType in lstType) 20 { 21 //2.通过接口上的特性取到需要的接口和实现类 22 var lstCustomAttr = oType.CustomAttributes; 23 //如果当前类上面存在属性标签 24 if (lstCustomAttr.Count() <= 0) 25 { 26 continue; 27 } 28 //获取第一个属性标签,并且判断是否相等于接口自定义属性 29 //如果相等,则为接口 30 var oInterfaceServiceAttribute = lstCustomAttr.FirstOrDefault(x => x.AttributeType.Equals(typeof(ServiceInterfaceAttribute))); 31 if (oInterfaceServiceAttribute != null) 32 { 33 lstTypeInterface.Add(oType); 34 continue; 35 } 36 //如果相等,则为类 37 var oClassServiceAttribute = lstCustomAttr.FirstOrDefault(x => x.AttributeType.Equals(typeof(ServiceClassAttribute))); 38 if (oClassServiceAttribute != null) 39 { 40 lstTypeClass.Add(oType); 41 } 42 } 43 44 //3.启动所有服务 45 foreach (var oInterfaceType in lstTypeInterface) 46 { 47 //在实现类集合中 获取由当前 Type 实现或继承的特定接口。 48 var lstTypeClassTmp = lstTypeClass.Where(x => x.GetInterface(oInterfaceType.Name) != null).ToList(); 49 if (lstTypeClassTmp.Count <= 0) 50 { 51 continue; 52 } 53 //如果当前类获取到的接口等于遍历的接口名称,则匹配成功, 54 if(lstTypeClassTmp[0].GetInterface(oInterfaceType.Name).Equals(oInterfaceType)) 55 { 56 var oTask = Task.Factory.StartNew(() => 57 { 58 OpenService(strBaseServiceUrl + "/" + oInterfaceType.Name, oInterfaceType, lstTypeClassTmp[0]); 59 }); 60 } 61 } 62 } 63 64 //通过服务接口类型和实现类型启动WCF服务 65 private void OpenService(string strServiceUrl, Type typeInterface, Type typeclass) 66 { 67 Uri httpAddress = new Uri(strServiceUrl); 68 using (ServiceHost host = new ServiceHost(typeclass))//需要添加System.SystemModel这个dll。。。。CSOAService这个为实现ICSOAService的实现类,WCF真正的实现方法再这个类里面 69 { 70 ///////////////////////////////////////添加服务节点/////////////////////////////////////////////////// 71 host.AddServiceEndpoint(typeInterface, new WSHttpBinding(), httpAddress);//ICSOAService这个为向外暴露的接口 72 if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) 73 { 74 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); 75 behavior.HttpGetEnabled = true; 76 behavior.HttpGetUrl = httpAddress; 77 host.Description.Behaviors.Add(behavior); 78 } 79 host.Opened += delegate 80 { 81 Console.ForegroundColor = ConsoleColor.Green; 82 Console.WriteLine("服务启动成功。服务地址:" + strServiceUrl); 83 }; 84 85 host.Open(); 86 while (true) 87 { 88 Console.ReadLine(); 89 } 90 } 91 } 92 } 93 }