通过继承ServiceHost编写简化MEX编程的类

 在WCF中完成同样的功能一般有2种选择:手工编码和撰写配置文件。MEX(Metadata Exchange)端点用于服务向外界发布其元数据,在WCF编程中非常常见。本文通过继承ServiceHost,编写一个简单的类来简化MEX的编程。通过这个扩展的类,不仅可以减少手工编码量,也可以减少配置文件的长度。

首先定义一个CollectionHelper类,该类提供了一个静态的泛型方法,用于判断一个实现ICollection接口的容器中是否有满足断言Predicate<T>的数据,代码实现如下:

using  System.Collections.Generic;

namespace  Kwan.WCFHelperLibrary
{
    
public   static   class  CollectionHelper
    {
        
public   static  Boolean Exists < T > (ICollection < T >  items, Predicate < T >  predicate)
        {
            
foreach  (T item  in  items)
            {
                
if  (predicate(item)  ==   true )
                    
return   true ;
            }
            
return   false ;
        }
    }
}

然后开始编写扩展的ServiceHost<T>类,该类继承于ServiceHost,类型参数作为调用ServiceHost构造器的参数。ServiceHost<T>的基本定义和构造器如下:

     ///   <summary>
    
///  该类用于简化MEX EndPoint编程
   
///   </summary>
    
///   <typeparam name="T"></typeparam>
     public   class  ServiceHost < T >  : ServiceHost
    {
        
///   <summary>
        
///  类构造器,调用基类构造器
       
///   </summary>
        
///   <param name="baseAddresses"> 基地址 </param>
         public  ServiceHost( params  Uri[] baseAddresses)
            : 
base ( typeof (T), baseAddresses)
        {
            
//  设置EnableMetadataExchange默认值为true
            EnableMetadataExchange  =   true ;
        }

ServiceHost<T>定义了2个Property。第一个Property为布尔型的HasMexEndPoints,用于指示该ServiceHost<T>实例是否含有MEX类型的端点

         public  Boolean HasMexEndPoints
        {
            
get
            {
                
//  使用匿名方法为Predicate<ServiceEndpoint>指定过程
                Predicate < ServiceEndpoint >  isMexEndPoint  =
                    
delegate (ServiceEndpoint endpoint)
                    {
                        
//  如果endpoint的契约类型为IMetadataExchange,则返回真值
                         return  endpoint.Contract.ContractType  ==   typeof (IMetadataExchange);
                    };

                
//  调用CollectionHelper的静态方法判断当前ServiceHost中是否存在MEX EndPoints
                 return  CollectionHelper.Exists(Description.Endpoints, isMexEndPoint);
            }
        }

在判断是否包含MEX类型的端点的代码中使用到了预先定义的CollectionHelper类中的泛型方法,使用匿名方法,保证代码的简洁。

第二个Property是该类的关键部分,布尔型的EnableMetadataExchange用于指示/设置该ServiceHost<T>实例是否允许发布元数据。实现如下:

         ///   <summary>
        
///  是否允许MEX
        
///   </summary>
         public  Boolean EnableMetadataExchange
        {
            
get
            {
                ServiceMetadataBehavior metadataBehavior;
                metadataBehavior 
=  Description.Behaviors.Find < ServiceMetadataBehavior > ();
                
if  (metadataBehavior  ==   null )
                {
                    
return   false ;
                }
                
return  metadataBehavior.HttpGetEnabled;
            }
            
            
set
            {
                
//  在ServiceHost打开的情况下不能设置该Property
                 if  (State  ==  CommunicationState.Opened)
                {
                    
throw   new  InvalidOperationException( " Host is already opened " );
                }

                ServiceMetadataBehavior metadataBehavior
                    
=  Description.Behaviors.Find < ServiceMetadataBehavior > ();

                
if  (metadataBehavior  ==   null )
                {
                    metadataBehavior 
=   new  ServiceMetadataBehavior();
                    Description.Behaviors.Add(metadataBehavior);
                }
                metadataBehavior.HttpGetEnabled 
=  value;

                
//  如果设置该Property为false,则移除所有MEX EndPoints
                
//  如果设置该Property为true,则添加所有MEX EndPoints
                 if  (value  ==   false )
                {
                    RemoveAllMexEndPoints();
                }
                
else
                {
                    
if  (HasMexEndPoints  ==   false )
                        AddAllMexEndPoints();
                }
            }
        }

在该Property的Setter中调用到了2个方法用于添加或者移除所有的MEX端点,而端点的信息来自于BaseAddresses成员,实现如下:

         ///   <summary>
        
///  添加所有的MEX EndPoints
        
///   </summary>
         private   void  AddAllMexEndPoints()
        {
            
foreach  (Uri baseAddress  in  BaseAddresses)
            {
                BindingElement bindingElement 
=   null ;
                
switch  (baseAddress.Scheme)
                {
                    
case   " net.tcp " :
                        {
                            bindingElement 
=   new  TcpTransportBindingElement();
                            
break ;
                        }
                    
case   " net.pipe " :
                        {
                            bindingElement 
=   new  NamedPipeTransportBindingElement();
                            
break ;
                        }
                    
case   " http " :
                        {
                            bindingElement 
=   new  HttpsTransportBindingElement();
                            
break ;
                        }
                    
case   " https " :
                        {
                            bindingElement 
=   new  HttpsTransportBindingElement();
                            
break ;
                        }
                }

                
if  (bindingElement  !=   null )
                {
                    Binding binding 
=   new  CustomBinding(bindingElement);
                    AddServiceEndpoint(
typeof (IMetadataExchange), binding,  " MEX " );
                }
            }
        }

        
///   <summary>
        
///  移除所有的MEX EndPoints
        
///   </summary>
         private   void  RemoveAllMexEndPoints()
        {
            
for  ( int  i  =   0 ; i  <  Description.Endpoints.Count; i ++ )
            {
                
if  (Description.Endpoints[i].Contract.ContractType  ==   typeof (IMetadataExchange))
                {
                    Description.Endpoints.RemoveAt(i);
                    i
-- ;
                }
            }
        }

现在我们来使用这个新的ServiceHost<T>,实例化。默认的情况下,EnableMetadataExchange为真,若在打开这个ServiceHost<T>之前将其设置为假,则将移除所有的MEX类型的端点。

_sh  =   new  ServiceHost < ServiceClass > ();

在未来,该类将被加以扩展,以进一步简化WCF的宿主端的编程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值