2015-11-03 87 views
0

我有一部分程序在发生某些事情时向我发送电子邮件和/或推送消息到我的iphone。这是通过使用MSMQ调用两个独立的WCF服务完成的。我遵循this指南(模型4.0),以使其通用并且测试友好。我喜欢创建通用通道,但我的问题是代理和通道工厂是否真正关闭/处理正确,或者是否会在达到10000个用户环境时崩溃(最终它会这样)。该代码完全适用于我的50个用户测试环境。正确使用C#中的工厂和服务代理处理WCF服务

因此,请查看下面的代码:

服务代理

public class ServiceProxy<TChannel> : IServiceProxy<TChannel> where TChannel : ICommunicationObject 
{ 
    private readonly TChannel InnerChannel; 

    public ServiceProxy(TChannel innerChannel) 
    { 
     this.InnerChannel = innerChannel; 
    } 

    public void Execute(Action<TChannel> operation) 
    { 
     try 
     { 
      operation(InnerChannel); 
      InnerChannel.Close(); 
     } 
     catch (CommunicationException) 
     { 
      InnerChannel.Abort(); 
     } 
     catch (TimeoutException) 
     { 
      InnerChannel.Abort(); 
     } 
     catch (Exception) 
     { 
      InnerChannel.Abort(); 
      throw; 
     } 
    } 

    public TResult Execute<TResult>(Func<TChannel, TResult> operation) 
    { 
     TResult result = default(TResult); 

     try 
     { 
      result = operation(InnerChannel); 
      InnerChannel.Close(); 
     } 
     catch (CommunicationException) 
     { 
      InnerChannel.Abort(); 
     } 
     catch (TimeoutException) 
     { 
      InnerChannel.Abort(); 
     } 
     catch (Exception) 
     { 
      InnerChannel.Abort(); 
      throw; 
     } 

     return result; 
    } 
} 

服务代理工厂

public class ServiceProxyFactory : IServiceProxyFactory 
{ 
    public IServiceProxy<TChannel> GetProxy<TChannel>(string endpointName) where TChannel : ICommunicationObject 
    { 
     var factory = new ChannelFactory<TChannel>(endpointName); 
     return new ServiceProxy<TChannel>(factory.CreateChannel()); 
    } 
} 

拨打服务电话(没有返回类型简单)

public class MessageSender : IMessageSender 
{ 
    private const string PushServiceEndpoint = "PushEndpointName"; 
    private const string MailServiceEndpoint = "MailEndpointName"; 

    private readonly IServiceProxyFactory ServiceProxyFactory; 

    public MessageSender() 
    { 
     ServiceProxyFactory = new ServiceProxyFactory(); 
    } 

    public void NotifyMe(*some args*) 
    { 
     ServiceProxyFactory.GetProxy<MailServiceChannel>(MailServiceEndpoint) 
        .Execute(a => a.SendEmail(*some args*)); 
    } 

的问题是:

我应该后执行关闭用于ServiceProxy?

是否明智每次我打电话GetProxy()时创建的ChannelFactory,并应本的ChannelFactory然后如果是再次关闭?

是不是真的表现友善生成的每个调用ServiceProxy? (这对我来说真的很重,但也许有人可以证明我错了)。

我留下了接口,从这个职位,但他们真的很简单,这整个设置与代理和接口的作品真的很好用单元测试和集成测试。

我希望你们中的一些编码向导对此有意见,并将分享这一点。

在此先感谢!

回答

1

主要性能影响创建了ChannelFactory

创建的ChannelFactory实例会带来一些开销,因为它涉及到以下操作: 构建ContractDescription树

Reflecting all of the required CLR types 

Constructing the channel stack 

Disposing of resources 

https://msdn.microsoft.com/en-us/library/hh314046%28v=vs.110%29.aspx

WCF团队已经实现缓存ClientBase<TChannel>类,很适合当你有自动生成的代理类。 由于您使用的是纯粹的ChannelFactory,您必须小心在每次调用时创建工厂,以获得更好的性能。

一个好的解决方案是实现缓存ChannelFactory<TChannel>你自己的(有a good idea如何做到这一点)。因此最后在ServiceProxyFactory而不是new ChannelFactory<TChannel>(endpointName);中,您应该使用像CachedChannelFactory<TChannel>.GetInstance()这样的缓存实例。

编辑:还有一个很好的文章米歇尔·勒鲁布斯塔曼特书面解释时To Cache or Not to Cache

+0

谢谢您的输入。你的“一个好主意”的链接是一个非常有趣的阅读。 虽然有一个问题:如果创建channelfactories是昂贵的操作,为什么不通过构造函数注入将ChannelFactory交给代理,然后为每个服务都有一个Service代理?通过这种方式,服务代理可以创建通道,执行某些操作并关闭通道... 这样,每个ServiceProxy都只有一个通道工厂,只能创建一次。 – ruNury

+0

我认为,你的解决方案也是一个可行的选择,只要确保你控制你的实例的生命周期。 –