加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

WCF 服务的集合管理器的设计

发布时间:2020-12-16 01:18:33 所属栏目:百科 来源:网络整理
导读:今天是2019年2月1日,时间过得针对,马上就年底了,当前新年也离我们越来越近了。在此,我也祝福经常浏览我博客的朋友们“新年快乐、阖家欢乐”,来年有一个好彩头。在即将结束这一年之计,写今年的最后一片文章。WCF 我相信大家都使用过,每次宿主该服务的

    今天是2019年2月1日,时间过得针对,马上就年底了,当前新年也离我们越来越近了。在此,我也祝福经常浏览我博客的朋友们“新年快乐、阖家欢乐”,来年有一个好彩头。在即将结束这一年之计,写今年的最后一片文章。WCF 我相信大家都使用过,每次宿主该服务的时候都要使用 ServiceHost,如果要加载多个 WCF 服务,那就需要多次 ServiceHost 实例化,而且这个过程大致都是一样的,这就有点太麻烦了。正好现在有时间,也有项目的需要,我就写了一份 WCF 服务的集合管理器,可以加载多个 WCF 服务,也可以对 WCF 的服务进行开启或者关闭的操作,使用起来还是比较方便的。这个设计已经改过多次,现在这个版本是目前最合适、最稳定的版本。

    说写就写,OO的三大基本原则,1、面向抽象编程,不要面向实现编程;2、多组合少继承;3、哪里有变化点就封装哪里。

    这三大原则我们要死死的记在心里,融化进血液里,由此,我的做法是做接口的抽象设计,代码如下:

    

    1、接口 IWcfServiceManager 的设计如下:

 1     /// <summary>
 2     /// WCF 服务的实例管理器,该类型可以实现对容器内部的 WCF 服务对象进行增加、删除、查询、开启和关闭的操作。
 3     </summary>
 4     public interface IWcfServiceManager:IDisposable
 5     {
 6          7          以指定的名称增加 WCF 服务实例,但是该服务并没有启动。
 8          9         <param name="serviceName">表示 WCF 服务的名称。</param>
10         <returns>返回布尔值,true 表示增加 WCF 服务成功,false 表示增加 WCF 失败。</returns>
11         bool AddService(string serviceName);
12 
13         14          从容器对象中删除指定名称的 WCF 服务实例。
15         16         17         返回布尔值,true 表示删除 WCF 服务成功,false 表示删除 WCF 服务失败。18         bool RemoveService(19 
20         21          获取所有的 WCF 服务实例的集合。
22         23         返回所有的 WCF 服务实例集合。24         IEnumerable<WcfService> GetServices();
25 
26         27          根据指定的名称获取 WCF 服务实例。
28         29         30         返回和指定名称相匹配的 WCF 服务实例,如果不存在则会返回 Null 值。31         WcfService GetService(32 
33         34          开启指定名称 WCF 服务实例,此时该服务可以为客户端提供服务了。
35         36         37         返回布尔值,true 表示成功开启 WCF 服务,false 表示开启式 WCF 服务失败。38         bool Start(39 
40         41          开启所有的 WCF 服务实例。
42         43         void StartAll();
44 
45         46          关闭指定名称的 WCF 服务实例,此时该服务就不能为客户端提供任何服务了。
47         48         49         返回布尔值,true 表示成功关闭 WCF 服务实例,false 表示关闭 WCF 服务实例失败。50         bool Close(51 
52         53          关闭所有的 WCF 服务实例,停止所有的服务。
54         55          CloseAll();        
56 
57         58          根据指定的名称来判断该 WCF 服务实例是否已经开启。
59         60         61         返回布尔值,true 表示该名称的 WCF 服务实例是已经开启的,false 表示该名称的 WCF 服务实例是未开启的。62         bool IsStartup(63 
64         65          获取 WCF 服务实例的个数
66         67         int Count { get; }
68     }

        这个接口的设计就不多说了,很简单,继续我们下一步。

?

    2、实现接口类的设计,类名是:WcfServiceManager.cs

      该类型都有详细的备注信息,不用我多说了。

  1       2       3       4     abstract class WcfServiceManager : IWcfServiceManager,IDisposable
  5   6         #region 私有字段
  7 
  8         private ConcurrentDictionary<string,ServiceHost> _serviceHostGroup;
  9          _serviceHostTemp;
 10         private [] _assemblyNames;
 11         bool _disposed;//是否回收完毕
 12         private IList<Assembly> _assemblies;
 13 
 14         #endregion
 15 
 16         #region 构造函数
 17 
 18          19          初始化 WcfServiceManager 类的实例
 20         </summary>        
 21         protected WcfServiceManager()
 22         {            
 23             _serviceHostGroup = new ConcurrentDictionary<();
 24             _serviceHostTemp = ();            
 25             _assemblies = new List<Assembly> 26         }
 27 
 28          29 
 30         #region 接口方法的实现
 31 
 32          33          34          35          36          37          serviceName)
 38         {
 39             if (string.IsNullOrEmpty(serviceName) || .IsNullOrWhiteSpace(serviceName))
 40             {
 41                 return false;
 42             }
 43             if (!_serviceHostGroup.ContainsKey(serviceName))
 44  45                 Type serviceType = GetServiceTypeFromAssemblies(serviceName,_assemblies);
 46                 if (serviceType != null)
 47                 {
 48                     ServiceHost host = new ServiceHost(serviceType);
 49                     _serviceHostGroup.TryAdd(serviceName,host);
 50                     true 51                 }
 52                 else
 53  54                      55  56  57              58  59 
 60          61          62          63          64          65          66  67              68  69                  70  71             if (_serviceHostGroup.ContainsKey(serviceName))
 72  73                 ServiceHost hostInstance =  74                 _serviceHostGroup.TryRemove(serviceName,out hostInstance);
 75                 if (hostInstance != null && hostInstance.State == CommunicationState.Opened)
 76  77                     hostInstance.Close();
 78                     hostInstance =  79  80                  81  82              83  84 
 85          86          87          88          89         public IEnumerable<WcfService> GetServices()
 90  91             IList<WcfService> list = new List<WcfService> 92             if (_serviceHostGroup != null && _serviceHostGroup.Count > 0 93  94                 foreach (var key in _serviceHostGroup.Keys)
 95  96                     var service =  WcfService();
 97                     service.ServiceName = _serviceHostGroup[key].Description.Name;
 98                     service.State = _serviceHostGroup[key].State;
 99                     service.Description = _serviceHostGroup[key].Description;
100                     list.Add(service);
101 102 103             return list;
104 105 
106         107         108         109         110         111         public WcfService GetService(112 113             114 115                 throw new ArgumentNullException("要查找的 WCF 服务的名称不能为空!");
116 117             WcfService service = 118             119 120                 service = 121                 service.ServiceName = _serviceHostGroup[serviceName].Description.Name;
122                 service.State = _serviceHostGroup[serviceName].State;
123                 service.Description = _serviceHostGroup[serviceName].Description;
124                  service;
125 126             127 128 
129         130          清空容器中所有 WCF 服务实例。
131         132          ClearAll()
133 134             135 136                 this.CloseAll();
137                 _serviceHostGroup.Clear();
138 139 140 
141         142         143         144         145         146         147 148             149 150                 151 152             var serviceHost = _serviceHostGroup[serviceName];
153             if (serviceHost != 154 155                 if (serviceHost.State == CommunicationState.Created && serviceHost.State != CommunicationState.Faulted)
156 157                     serviceHost.Open();
158                     159 160                 else if (serviceHost.State == CommunicationState.Closed || serviceHost.State !=161 162                     ServiceHost tempHost;                    
163                     _serviceHostGroup.TryRemove(serviceName,1)"> tempHost);
164                     if (tempHost != 165                     {
166                         if (tempHost.State ==167                         {
168                             tempHost.Close();
169                         }
170                         tempHost = 171                     }
172                     ServiceHost newhost =  ServiceHost(serviceHost.Description.ServiceType);
173                     newhost.Open();
174 175                     176 177 178             179 180 
181         182         183         184          StartAll()
185 186             187 188                 foreach (ServiceHost host  _serviceHostGroup.Values)
189 190                     if (host.State !=191 192                         if (host.State == CommunicationState.Closed)
193 194                             ServiceHost newhost =  ServiceHost(host.Description.ServiceType);
195                             newhost.Open();
196                             _serviceHostTemp.TryAdd(host.Description.ConfigurationName,1)">197 198                         199 200                             ServiceHost newhost = 201 202 203 204                          CommunicationState.Created)
205 206                             host.Open();
207 208 209 210 211             if (_serviceHostTemp != null && _serviceHostTemp.Count > 212 213                 foreach (KeyValuePair< _serviceHostTemp)
214 215                      (_serviceHostGroup.ContainsKey(item.Key))
216 217                         if (_serviceHostGroup[item.Key].State ==218 219                             _serviceHostGroup[item.Key].Close();
220 221                         ServiceHost tempHost;
222                         _serviceHostGroup.TryRemove(item.Key,1)">223                         if (tempHost.State !=224 225 226                             tempHost = 227 228                         if (item.Value.State ==229 230                             item.Value.Open();
231 232                         _serviceHostGroup.TryAdd(item.Key,item.Value);
233 234 235                 _serviceHostTemp.Clear();
236 237 238 
239         240         241         242         243         244         245 246             247 248                 249 250             var host =251             if (host != 252 253                 254 255                     host.Close();                    
256 257                 258 259             260 261 
262         263         264         265          CloseAll()
266 267             268 269                 270 271                     272 273                         host.Close();
274 275 276 277         }        
278 
279         280         281         282         283         284         285 286             287 288                 289 290             291             292 293                 294 295                     296 297 298             299 300 
301         302          重新加载所有的 WCF 服务实例,并将所有的 WCF 服务对象开启
303         304          Reload()
305 306             307             .ClearAll();
308             .Initialize();
309             .StartAll();
310 311 
312         313         314         315         int Count
316 317             get
318 319                  _serviceHostGroup.Count;
320 321 322 
323         324 
325         #region 定义的抽象方法
326 
327         328          加载所有的 WCF 服务实例对象
329         330         <param name="assemblyFullNames">承载 WCF 服务的应用程序集的完全限定名数组331         void Initialize(params [] assemblyFullNames)
332 333             _assemblyNames = assemblyFullNames;
334             CloseAll();
335             ClearAll();
336 
337             var currentDomainDlls = GetAssembliesFromCurrentDomain();
338             var specifiedDlls = GetAssembliesFromSpecifiedCondition(_assemblyNames);
339             var item  currentDomainDlls)
340 341                 _assemblies.Add(item);
342 343              specifiedDlls)
344 345 346 347 
348             Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
349             ServiceModelSectionGroup serviceModelGroup = config.GetSectionGroup(system.serviceModel") as ServiceModelSectionGroup;
350             if (serviceModelGroup != 351 352                 foreach (ServiceElement service  serviceModelGroup.Services.Services)
353 354                     .AddService(service.Name);
355 356 357 358 
359         360          根据指定的字符串类型的程序集名称列表获取强类型的程序集列表
361         362         返回获取到的强类型的程序集列表363         protected virtual IList<Assembly> GetAssembliesFromSpecifiedCondition([] assemblyNames)
364 365             IList<Assembly> assemblies = 366             if (assemblyNames != null && assemblyNames.Length > 367 368                  assemblyNames)
369 370                     var assembly = Assembly.Load(item);
371                     assemblies.Add(assembly);
372 373 374              assemblies;
375 376 
377         378          根据当前的应用程序域获取所有必需的程序集
379         380         返回获取到当前应用程序域内的程序集列表381         virtual IList<Assembly> GetAssembliesFromCurrentDomain()
382 383             IList<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => (!a.FullName.StartsWith(System",StringComparison.OrdinalIgnoreCase) && (!a.FullName.StartsWith(Microsoftmscorlibvshost32SMDiagnostics,StringComparison.OrdinalIgnoreCase)))).ToList();
384             385 386 
387         388          根据 WCF 服务的名称在当前程序域中或者传入的程序集中查找该服务的 Type 类型的对象
389         390         要查找的 WCF 服务的名称391         <param name="assemblies">承载 WCF 服务的程序集列表392         返回WCF服务的Type类型的对象,如果没有找到相应的类型就会返回 Null 值。393         private Type GetServiceTypeFromAssemblies(string serviceName,IList<Assembly> assemblies)
394 395             396 397                 398 399 
400             if (assemblies == null || assemblies.Count == 401 402                 待查找的程序集列表不能为空!403 404 
405             try
406 407                 if (assemblies != null && assemblies.Count() > 408 409                     var currentAssembly = assemblies.FirstOrDefault(a => a.GetType(serviceName) != 410                     if (currentAssembly != 411 412                          currentAssembly.GetType(serviceName);
413 414 415 416             catch (Exception)
417 418                 throw419 420             421 422 
423         424 
425         #region IDispoable模式
426 
427         428          释放托管资源
429         430          Dispose()
431 432             Dispose(433             GC.SuppressFinalize(434 435 
436         437          析构函数释放资源
438         439         ~WcfServiceManager()
440 441             Dispose(442 443 
444         445          释放所有的托管资源和非托管资源核心方法实现
446         447         <param name="disposing">是否需要释放那些实现IDisposable接口的托管对象448         virtual void Dispose(bool disposing)
449 450              (_disposed)
451 452                 return; 如果已经被回收,就中断执行
453 454              (disposing)
455 456                 TODO:回收托管资源,调用IDisposable的Dispose()方法就可以
457                 458                 459                 _serviceHostGroup = 460 461             TODO:释放非托管资源,设置对象为null
462             _disposed = 463 464 
465         466     }

?

    3、真正实现的叶子结点类型设计,类型是:DefaultWcfServiceManager.cs

        该类型就是用户将要使用的类型。

        

sealed  DefaultWcfServiceManager:WcfServiceManager,1)"> 6          7 
 初始化 DefaultWcfServiceManager 类型的实例
public DefaultWcfServiceManager(){ }
13         14     }

      主要的类型就差不多了。在这个设计过程中,还会涉及到一个辅助类型?WcfService

?

    4、辅助类型?WcfService 的设计编码。很简单,直接上代码。

      

 WCF 服务实例的类型的定义
 WcfService
 8          _serviceName;
 9         private CommunicationState _communicationState;
10          ServiceDescription _serviceDescription;
11 
12         13 
14         15 
 初始化 WcfService 类型的实例
18         19          WcfService()
20         { }
21 
22         23 
24         #region 实例属性
 获取或者设置 WCF 服务实例的名称
29          ServiceName
30 31             get {  _serviceName; }
32             set
33 34                 if ((!string.IsNullOrEmpty(value)) && (!.IsNullOrWhiteSpace(value)))
35 36                     _serviceName = value;
37 38 39 40 
 获取或者设置 WCF 的服务实例的运行状态
43         44          CommunicationState State
45 46              _communicationState; }
47             set { _communicationState = value; }
48 49         
50         51          获取或者设置 WCF 服务的描述信息
53          ServiceDescription Description
54 55              _serviceDescription; }
56             57 58                 if (value != 59 60                     _serviceDescription =61 62 63 64 
65         66     }

?

    5、单元测试项目代码。

        这是最后的代码了,有源码没有测试代码,似乎还少一点。测试代码如下:

        

 1      Program
 2  3         static void Main([] args)
 4  5             DefaultWcfServiceManager hosts = new DefaultWcfServiceManager("ServiceInstance,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null");
 6             DefaultWcfServiceManager hosts =  DefaultWcfServiceManager();
 7             hosts.Initialize(ServiceInstance,PublicKeyToken=null 8             hosts.Initialize("ServiceInstance");
 9             string operation = a10             do
11 12                 operation = Console.ReadLine();
13                 string.Compare(operation,StartAlltrue) == 14 15                     hosts.StartAll();
16                     Console.WriteLine(已经全部打开17 18 
19                 ConsoleService21                     hosts.Close(ServiceInstance.ConsoleService22                     Console.WriteLine(ConsoleService 已经关闭23 24 
25                 ConsoleServiceOpen26 27                     hosts.Start(28                     Console.WriteLine(ConsoleService 已经打开29 30 
31                 MathServiceOpen32 33                     hosts.Start(ServiceInstance.MathService34                     Console.WriteLine(MathService 已经打开36 
37                 MathService39                     hosts.Close(40                     Console.WriteLine(MathService 已经关闭41 42 
43                 CloseAll44                     hosts.CloseAll();
46                     Console.WriteLine(已经全部关闭47 48 
49                 Reload50 51                     hosts.Reload();
52                     Console.WriteLine(已经全部重新打开53 54                 print55 56                      hosts.GetServices())
58                         Console.WriteLine(服务地址:" + item.Description.Endpoints[0].Address.Uri.ToString() + ;状态:" + item.State.ToString());
60 61             } while (exittrue) != 63     }

?

    总结:

      好了,就写到这里吧。要想使用 WCF ,必须的命名空间是必须要引入的 System.ServiceModel,当然这里省略了必要的配置数据了,我相信,这个不是很难。也要说明一点,我这个项目是放在类库里面的,WCF 是分为 Client 端和 Server 端的,今天只是贴出了服务器端的代码,如果有需要,在把客户端生成代理类的代码贴出来。年尾了,让不好的东西过去,让自己迎接新的明天,不忘初心,继续努力。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读