【问题标题】:Object instances in static classes静态类中的对象实例
【发布时间】:2012-02-14 21:47:47
【问题描述】:

我正在开发一个包含多个 WCF 服务引用的 Web 应用程序。目前,每次我们需要调用服务时,我们都会执行以下操作(例如):

Service.ServiceClient ServiceClient = new Service.ServiceClient();
ServiceClient.SomeMethod();

最好有一个静态类,其中包含对每个服务的静态引用,然后调用该类,从而避免每次我们想要调用它时都创建一个新的 ServiceClient 对象实例?

例如:

public static class Services
{
    private static Service.ServiceClient _ServiceClient = new Service.ServiceClient();
    public Service.ServiceClient ServiceClient
    {
        get
        {
            return _ServiceClient;
        }
    }
}

而且,如果这样做,行会

private static Service.ServiceClient _ServiceClient = new Service.ServiceClient();

每次我们尝试调用该对象时都会创建一个新对象,或者每次我们调用它时它都会是该对象的同一个实例?

【问题讨论】:

  • 它将在每次调用时创建一个新实例,不管下面的通道工厂如何在不同实例之间共享资源,这就是为什么你必须在完成每个实例后关闭()以释放共享的所有实例之间的资源。
  • 另外,如果您对所有调用都使用相同的代理对象,并且由于某种原因调用失败,则除非您 Abort() 和长篇大论,否则该对象将无法使用。它被设计为以这种方式使用,创建代理的实例,调用您的方法,最后关闭()实例。

标签: c# wcf service-reference


【解决方案1】:

您可以拥有一个包含数据合约公开的所有功能的类。所有这些方法都是静态的。现在在这些函数中,您可以执行以下操作

public class ServiceManager{
    public static CalculatedData SomeMethod()
    {
         var client = GetClient();
         try
         {
             return client.SomeMethod();
         }
         catch(Exception ex)
         {
             //Handle Error
         }
         finally
         {
             if(client.State == System.ServiceModel.CommunicationState.Opened)
                client.Close();
         } 

    }
    private static SomeClient GetClient()
    {
         return new ServiceClient();
    }
} 

消费者会像消费它

var calculatedData = ServiceManager.SomeMethod();

【讨论】:

    【解决方案2】:

    如果你想这样做,请创建

    Singleton Service

    单例服务是最终的可共享服务。当服务配置为单例时,所有客户端都独立连接到同一个知名实例,而不管它们连接到服务的哪个端点。单例服务永远存在,只有在主机关闭后才会被处理掉。单例仅在创建主机时创建一次。

    您可以通过将 InstanceContextMode 属性设置为 InstanceContextMode.Single 来配置单例服务:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    class MySingleton : ...
    {...}
    

    【讨论】:

    • 我认为这不是 OP 想要实现的目标
    【解决方案3】:

    它只会被创建一次,但是你无法控制它何时被创建。处理此问题的常用方法是创建一个单独的静态方法(例如 init),您可以在其中创建实例,或者在第一次调用时创建它。你应该检查singleton design pattern这个。

    【讨论】:

    • 嗯,我想到了这个,但这不是一个很好的解决方案。另外,我认为使用 static{} 构造函数也没有多大用处:?。
    【解决方案4】:

    您可以使用如下帮助器:

    private delegate void ServiceAction(Service.ServiceClient client);
    
    private static void PerformServiceAction(ServiceAction serviceAction)
    {
      using (var client = new Service.ServiceClient())
      {
        serviceAction(client);
      }
    }
    

    然后可以通过以下方式调用:

    Helper.PerformServiceAction(client => client.SomeMethod());
    

    它仍然为每个调用或调用序列创建一个代理,但至少您的调用代码更轻。

    (请记住,对 wcf 客户端代理使用“使用”不是一个好主意,因为 dispose 可能会引发异常,因此最好手动捕获异常并优雅地关闭代理)。

    【讨论】:

    • 是的,但是如果发生任何异常,客户端应该被中止,不是吗?
    • @ArsenMkrt 是的,但使用 using 可能会触发隐藏到原始异常的异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多