2012-03-29 66 views
0

这是我用来调用方法:修改现有的WCF通信对象

SvcHelper.Using<SomeWebServiceClient>(proxy => 
{ 
    proxy.SomeMethod(); 
} 

public class SvcHelper 
{ 
    public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable, new() 
    { 
    } 
} 

这是我如何调用方法:

ChannelFactory<ISomethingWebService> cnFactory = new ChannelFactory<ISomethingWebService>("SomethingWebService"); 
ISomethingWebService client = cnFactory.CreateChannel(); 

using (new OperationContextScope((IContextChannel)client)) 
{ 
    client.SomeMethod(); 
} 

我的问题是:如果不更换的每个实例我原来的方法调用方法;是否有修改我SvcHelper,做在SvcHelper构造通道的创建方式,然后简单地通过类似如下的界面:

SvcHelper.Using<ISomethingWebService>(client => 
{ 
    client.SomeMethod(); 
} 

希望这是有道理的,并在此先感谢。

回答

1

首先,你不希望创建一个新的ChannelFactory<T>每次调用使用的辅助方法。他们是WCF世界中构建成本最高的东西。因此,至少,您会希望在那里使用缓存方法。

其次,你不想把自己绑在“客户”类型上。只需使用服务合约界面即可。

从你有什么开始,这里就是我会去根据我如何在过去做到了这一点:

public class SvcHelper 
{ 
    private static ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory> ChannelFactories = new ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory>(); 

    public static void Using<TServiceContract>(Action<TServiceContract> action) where TServiceContract : class 
    { 
     SvcHelper.Using<TServiceContract>(action, "*"); 
    } 

    public static void Using<TServiceContract>(Action<TServiceContract> action, string endpointConfigurationName) where TServiceContract : class 
    { 
     ChannelFactoryCacheKey cacheKey = new ChannelFactoryCacheKey(typeof(TServiceContract), endpointConfigurationName); 

     ChannelFactory<TServiceContract> channelFactory = (ChannelFactory<TServiceContract>)SvcHelper.ChannelFactories.GetOrAdd(
                                   cacheKey, 
                                   missingCacheKey => new ChannelFactory<TServiceContract>(missingCacheKey.EndpointConfigurationName)); 

     TServiceContract typedChannel = channelFactory.CreateChannel(); 
     IClientChannel clientChannel = (IClientChannel)typedChannel; 

     try 
     { 
      using(new OperationContextScope((IContextChannel)typedChannel)) 
      { 
       action(typedChannel); 
      } 
     } 
     finally 
     { 
      try 
      { 
       clientChannel.Close(); 
      } 
      catch 
      { 
       clientChannel.Abort(); 
      } 
     } 

    } 

    private sealed class ChannelFactoryCacheKey : IEquatable<ChannelFactoryCacheKey> 
    { 
     public ChannelFactoryCacheKey(Type channelType, string endpointConfigurationName) 
     { 
      this.channelType = channelType; 
      this.endpointConfigurationName = endpointConfigurationName; 
     } 

     private Type channelType; 

     public Type ChannelType 
     { 
      get 
      { 
       return this.channelType; 
      } 
     } 

     private string endpointConfigurationName; 

     public string EndpointConfigurationName 
     { 
      get 
      { 
       return this.endpointConfigurationName; 
      } 
     } 

     public bool Equals(ChannelFactoryCacheKey compareTo) 
     { 
      return object.ReferenceEquals(this, compareTo) 
         || 
        (compareTo != null 
         && 
        this.channelType == compareTo.channelType 
         && 
        this.endpointConfigurationName == compareTo.endpointConfigurationName); 
     } 

     public override bool Equals(object compareTo) 
     { 
      return this.Equals(compareTo as ChannelFactoryCacheKey); 
     } 

     public override int GetHashCode() 
     { 
      return this.channelType.GetHashCode()^this.endpointConfigurationName.GetHashCode(); 
     } 
    } 
} 
+0

嗯不知道为什么你必须删除该...除非你已经使这些方法非静态?在我粘贴之前,我正在编译该示例代码。为了清晰起见,我更喜欢带前缀的方法调用,所以我总是以此为前缀。或ClassName。在静态调用的情况下。 – 2012-03-30 01:21:40

+0

我是否还需要实现缓存以及此方法? – fuzz 2012-04-01 07:52:51

+1

那么我有channelFactory实例缓存在那里通道类型,但我忘了我们实际上需要缓存Type + endpointConfiguration名称是一个完整的实现。我会更新实施以完成。 – 2012-04-01 16:41:12

1

这应该工作:

public class SvcHelper 
{ 
    public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable 
    { 
     ChannelFactory<TClient> cnFactory = new ChannelFactory<TClient>("SomethingWebService"); 
     TClient client = cnFactory.CreateChannel(); 
     using (new OperationContextScope((IContextChannel)client)) 
     { 
      action(client); 
     } 
    } 
} 
+0

的问题是,传递给通用'ChannelFactory'类型参数类必须是接口类型。它表示没有从接口到'ICommunicationObject'的转换。 – fuzz 2012-03-29 06:09:07

+0

也许这是有道理的删除“TClient:ICommunicationObject,IDisposable” – 2012-03-29 06:24:47