• WCF自寄宿


    WCF很早就出现了,然而我感受到能够让新手重点去学习WCF而不是WebService是最近两年。我相信大部分人初步了解WCF的时候会很痛苦,尤其是生成代理类,以及配置的问题。我本人其实比较讨厌配置编程,但喜欢轻量配置,因此也一直研究如何自己定义配置节点,去让WCF服务识别,然后重量级ABC操作由编码来完成。下面,我将会提供一个我本人用于学习其他知识需要使用WCF时的开发模式,另外说明,为了更好的说明,我将提供的都是精简版本,并不适合用于测试生产的例子。

    1.定义适合自己的配置

     1 public class WCFServiceElement : ConfigurationElement
     2 {
     3         [ConfigurationProperty(name: "ServiceName", IsRequired = false)]
     4         public string ServiceName
     5         {
     6             get
     7             {
     8                 return (base["ServiceName"] as string);
     9             }
    10             set
    11             {
    12                 base["ServiceName"] = value;
    13             }
    14         }
    15 
    16         [ConfigurationProperty(name: "ServiceAssembly", IsRequired = false)]
    17         public string ServiceAssembly
    18         {
    19             get
    20             {
    21                 return (base["ServiceAssembly"] as string);
    22             }
    23             set
    24             {
    25                 base["ServiceAssembly"] = value;
    26             }
    27         }
    28 
    29         [ConfigurationProperty(name: "InterfaceServiceName", IsRequired = false)]
    30         public string InterfaceServiceName
    31         {
    32             get
    33             {
    34                 return (base["InterfaceServiceName"] as string);
    35             }
    36             set
    37             {
    38                 base["InterfaceServiceName"] = value;
    39             }
    40         }
    41 
    42         [ConfigurationProperty(name: "InterfaceServiceAssembly", IsRequired = false)]
    43         public string InterfaceServiceAssembly
    44         {
    45             get
    46             {
    47                 return (base["InterfaceServiceAssembly"] as string);
    48             }
    49             set
    50             {
    51                 base["InterfaceServiceAssembly"] = value;
    52             }
    53         }
    54 
    55         [ConfigurationProperty(name: "IPAddress", IsRequired = false)]
    56         public string IPAddress
    57         {
    58             get
    59             {
    60                 return (base["IPAddress"] as string);
    61             }
    62             set
    63             {
    64                 base["IPAddress"] = value;
    65             }
    66         }
    67 
    68         [ConfigurationProperty(name: "Binding", IsRequired = false)]
    69         public string Binding
    70         {
    71             get
    72             {
    73                 return (base["Binding"] as string);
    74             }
    75             set
    76             {
    77                 base["Binding"] = value;
    78             }
    79         }
    80 }
    View Code
     1 public class WCFServicesElementCollection : ConfigurationElementCollection
     2     {
     3         protected override ConfigurationElement CreateNewElement()
     4         {
     5             ConfigurationElement _element = new WCFServiceElement();
     6             return _element;
     7         }
     8 
     9         protected override object GetElementKey(ConfigurationElement element)
    10         {
    11             WCFServiceElement _element = (WCFServiceElement)element;
    12             return _element.ServiceName;
    13         }
    14 
    15         protected override string ElementName
    16         {
    17             get
    18             {
    19                 return "WCFService";
    20             }
    21         }
    22 
    23         public override ConfigurationElementCollectionType CollectionType
    24         {
    25             get
    26             {
    27                 return ConfigurationElementCollectionType.BasicMap;
    28             }
    29         }
    30 }
    View Code
     1 public class WCFServiceSection : ConfigurationSection
     2 {
     3         [ConfigurationProperty(name: "", IsDefaultCollection = true, IsRequired = false)]
     4         public WCFServicesElementCollection WCFServices
     5         {
     6             get
     7             {
     8                 return (base[""] as WCFServicesElementCollection);
     9             }
    10             set
    11             {
    12                 base[""] = value;
    13             }
    14         }
    15 }
    View Code
     1 <?xml version="1.0" encoding="utf-8" ?>
     2 <configuration>
     3   <configSections>
     4     <section name="WCFServices" type="Basic.Configuration.WCFServiceSection,Basic.Data"/>
     5   </configSections>
     6   <WCFServices>
     7     <WCFService ServiceName="AppManagementImplementation"
     8 ServiceAssembly="Service.BackgroundManagement.Implementation"
     9                           InterfaceServiceName="IAppManagement"
    10 InterfaceServiceAssembly="Service.BackgroundManagement.Interface"
    11                           IPAddress="http://192.168.1.4:8085/AppManagementService" 
    12                           Binding="WSHttpBinding">
    13     </WCFService>
    14   </WCFServices>
    15 </configuration>
    View Code

    这里注意的是configSections一定要放在第一行,这个倒是听让人无语的。当然配置可以用自己希望方式配置,我这里提供一个简单的思路。

    2.定义适合自己的WCFServerConfigurationManagement

     1 public abstract class WCFServerConfigurationManagement
     2 {
     3         private static HybridDictionary _Collection = new HybridDictionary();
     4 
     5         public static void Register()
     6         {
     7             WCFServiceSection section = ConfigurationManager.GetSection("WCFServices") as WCFServiceSection;
     8             if (null == section)
     9             {
    10                 throw new NullReferenceException("未能识别WCFServices,请确认configSections配置节点");
    11             }
    12 
    13             _Collection.Clear();
    14 
    15             foreach (WCFServiceElement element in section.WCFServices)
    16             {
    17                 Assembly assemblyInterfaceService = Assembly.Load(element.InterfaceServiceAssembly);
    18                 Assembly assemblyService = Assembly.Load(element.ServiceAssembly);
    19 
    20                 Type typeInterface = assemblyInterfaceService.ExportedTypes.FirstOrDefault(type => type.Name.Equals(element.InterfaceServiceName));
    21                 Type typeImplement = assemblyService.ExportedTypes.FirstOrDefault(type => type.Name.Equals(element.ServiceName));
    22 
    23                 if (null == typeInterface && null == typeImplement)
    24                 {
    25                     throw new NullReferenceException("无法加载服务");
    26                 }
    27 
    28                 ServiceHost _NewHost = new ServiceHost(typeImplement);
    29                 Binding binding = CreateBinding(element.Binding);
    30                 _NewHost.AddServiceEndpoint(typeInterface, binding, element.IPAddress);
    31                 
    32                 _NewHost.Opened += (sender, e) =>
    33                 {
    34 #if DEBUG
    35                     Console.WriteLine($"服务:{element.ServiceName} 已经开启.");
    36 #endif
    37                 };
    38                 _NewHost.Open();
    39             }
    40         }
    41 
    42         public static Binding CreateBinding(string bindingType)
    43         {
    44             Binding _Binding = default(Binding);
    45             switch (bindingType)
    46             {
    47                 case "BasicHttpBinding":
    48                     _Binding = new BasicHttpBinding();
    49                     break;
    50                 case "WSHttpBinding":
    51                     _Binding = new WSHttpBinding();
    52                     break;
    53                 case "WS2007HttpBinding":
    54                     _Binding = new WS2007HttpBinding();
    55                     break;
    56                 default:
    57                     throw new ArgumentNullException("根据接口名称无法匹配绑定类型");
    58             }
    59 
    60             return _Binding;
    61         }
    62 }
    View Code

    这里主要用来根据配置动态配置WCF ServiceHost 和 Binding 的.然后再您的Custom Host 里面调用如下:

    1 class Program
    2 {
    3         static void Main(string[] args)
    4         {
    5             WCFServerConfigurationManagement.Register();
    6 
    7             Console.ReadLine();
    8         }
    9 }
    View Code

    3.定义适合自己的WCFClientConfigurationManagement

     1 public abstract  class WCFClientConfigurationManagement
     2 {
     3         private static HybridDictionary _Collection = new HybridDictionary();
     4 
     5         public static void Register()
     6         {
     7             WCFServiceSection section = ConfigurationManager.GetSection("WCFServices") as WCFServiceSection;
     8             if (null == section)
     9             {
    10                 throw new NullReferenceException("未能识别WCFServices,请确认configSections配置节点");
    11             }
    12 
    13             _Collection.Clear();
    14 
    15             foreach (WCFServiceElement element in section.WCFServices)
    16             {
    17                 _Collection.Add(element.InterfaceServiceName , element);
    18             }
    19         }
    20 
    21         public static Binding CreateBinding(string serviceName)
    22         {
    23             Binding _Binding = default(Binding);
    24             WCFServiceElement element = _Collection[serviceName] as WCFServiceElement;
    25             if (null == element)
    26             {
    27                 Register();
    28                 element = _Collection[serviceName] as WCFServiceElement;
    29                 if (null == element)
    30                 {
    31                     throw new NullReferenceException("可能配置出现严重错误,根据接口名称无法获取配置文件信息.");
    32                 }
    33             }
    34 
    35             switch (element.Binding)
    36             {
    37                 case "BasicHttpBinding":
    38                     _Binding = new BasicHttpBinding();
    39                     break;
    40                 case "WSHttpBinding":
    41                     _Binding = new WSHttpBinding();
    42                     break;
    43                 case "WS2007HttpBinding":
    44                     _Binding = new WS2007HttpBinding();
    45                     break;
    46                 default:
    47                     throw new ArgumentNullException("根据接口名称无法匹配绑定类型");
    48             }
    49 
    50             return _Binding;
    51         }
    52 
    53         public static EndpointAddress CreateAddress(string serviceName)
    54         {
    55             WCFServiceElement element = _Collection[serviceName] as WCFServiceElement;
    56             if (null == element)
    57             {
    58                 Register();
    59                 element = _Collection[serviceName] as WCFServiceElement;
    60                 if (null == element)
    61                 {
    62                     throw new NullReferenceException("可能配置出现严重错误,根据接口名称无法获取配置文件信息.");
    63                 }
    64             }
    65 
    66             EndpointAddress _Address = new EndpointAddress(element.IPAddress);
    67             return _Address;
    68         }
    69 }
    View Code

    这里主要用来根据配置动态配置WCF Client 和 Binding 的。然后再您的客户端以及配置文件注册如下(我这里提供的是ASP.NET MVC 5 的环境):

     1 public class MvcApplication : HttpApplication
     2 {
     3         protected void Application_Start()
     4         {
     5             AreaRegistration.RegisterAllAreas();
     6             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
     7             RouteConfig.RegisterRoutes(RouteTable.Routes);
     8             BundleConfig.RegisterBundles(BundleTable.Bundles);
     9 
    10             WCFClientConfigurationManagement.Register();
    11         }
    12  }
    View Code
     1 <configuration>
     2   <configSections>
     3     <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
     4     <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
     5     <section name="WCFServices" type="Basic.Configuration.WCFServiceSection,Basic.Data"/>
     6   </configSections>
     7 <WCFServices>
     8     <WCFService InterfaceServiceName="IAppManagement"
     9                           IPAddress="http://192.168.1.4:8085/AppManagementService"
    10                           Binding="WSHttpBinding">
    11     </WCFService>
    12 </WCFServices>
    13 </configuration>
    View Code

    4.定义适合自己的WCF ClientBase

     1 public class WCFClient
     2 {
     3         public static TResult ClientInvoke<TChannel , TResult>(Func<TChannel , TResult> functionInvoke)
     4         {
     5             string _ServiceName = typeof(TChannel).Name;
     6             Binding binding = WCFClientConfigurationManagement.CreateBinding(_ServiceName);
     7             EndpointAddress address = WCFClientConfigurationManagement.CreateAddress(_ServiceName);
     8             TChannel _channel = ChannelFactory<TChannel>.CreateChannel(binding, address);
     9             TResult _Result = functionInvoke.Invoke(_channel);
    10             return _Result;
    11         }
    12 }
    View Code

    以上交代完毕,当然提醒初步了解WCF的人IPAddress 配置也可以写*.svc地址,可以在自寄宿在Windows Service 里,也可以是IIS宿主环境。写到这里,希望这篇随笔能帮助到需要帮助的人,这也就是它的价值所在了。

  • 相关阅读:
    CSP2019滚粗记
    [总结] wqs二分学习笔记
    [总结] 圆方树学习笔记
    [CF960G] Bandit Blues
    [总结] 第一类斯特林数
    [EOJ629] 两开花
    [CF286E] Ladies' shop
    [总结] 动态DP学习笔记
    [BZOJ3879] SvT
    [总结] 替罪羊树学习笔记
  • 原文地址:https://www.cnblogs.com/blakebook/p/5380097.html
Copyright © 2020-2023  润新知