在 C# 中使用工厂和服务代理更正 WCF 服务处理

Correct WCF service handling using a factory and service proxies in C#

我的程序有一部分会在发生某些事情时向我的 iphone 发送电子邮件 and/or 推送消息。这是通过使用 MSMQ 调用两个单独的 WCF 服务来完成的。我遵循 this 指南(模型 4.0)以使其通用且测试友好。我喜欢通用通道创建,但我的问题是代理和通道工厂是否真的 closed/disposed 正确,或者当它达到 10000 个用户环境(它最终会)时是否会爆炸。该代码在我的 50 个用户测试环境中完美运行。

因此,请查看以下代码:

服务代理

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());
    }
}

进行服务调用(为简单起见,不输入 return)

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真的性能友好吗? (这对我来说似乎很沉重,但也许有人可以证明我是错的)。

我从这个 post 中省略了接口,但它们真的很简单,而且这个带有代理和接口的整个设置非常适合单元和集成测试。

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

提前致谢!

主要的性能影响是创建 ChannelFactory

Creating ChannelFactory instances incurs some overhead because it involves the following operations: Constructing the ContractDescription tree

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> class 实现了缓存,当你有自动生成的代理 classes 时它是合适的。 当您使用纯 ChannelFactory 时,您必须小心在每次调用时创建工厂,以获得更好的性能。

一个好的解决方案是实现自己的 ChannelFactory<TChannel> 缓存(a good idea 介绍了如何做到这一点)。所以最后在你的 ServiceProxyFactory 而不是 new ChannelFactory<TChannel>(endpointName); 你应该使用像 CachedChannelFactory<TChannel>.GetInstance().

这样的缓存实例

编辑: Michele Leroux Bustamante 写了另一篇很好的文章,解释了 To Cache or Not to Cache