首页 文章

我们是否应该为C#中的Microsoft.Rest.ServiceClient派生的客户使用Singletons?

提问于
浏览
4

使用swagger规范生成的Azure .NET SDK(例如与Azure Resource Manager关联的那些)时,生成的库利用Microsoft AutoRest Client Runtime,各种“Clients”都继承自“ServiceClient” .

我们一直在使用DocumentDB Client,并阅读了很多关于在.NET中使用本机HttpClient的问题 . 尽管使用单例模式存在众所周知的问题,但Microsoft建议对这两个客户端使用单例模式,因为它们在内部工作 . 在这些情况下,这是必要的 .

因此,我们为这些案例制定了使用和管理单例的策略,因此我们想知道是否应该对从ServiceClient派生的Azure REST客户端使用相同的策略 . 如果它使用HttpClient,那将是有道理的 .

注意:这个问题不是寻找关于单身人士或客户的一般开发人员建议的问题,而是基于对其内部工作的了解而与AutoRest客户端运行时相关联的Microsoft开发团队的特定问题 .

3 回答

  • 1

    是的,不是 . :-)您不需要使用Singleton设计模式,但建议尽可能共享 ServiceClient -派生的实例,因为每个实例都封装了一个 HttpClient .

    对于某些Azure库,并不总是可以共享单个客户端 . 例如,Azure搜索库中的 SearchIndexClient 一次只能定位一个索引,因此如果您的应用程序使用多个索引,则需要以某种方式对它们进行池化 . Here is a related question on this topic与其他地方的其他讨论有关联 .

  • 1

    我一直试图解决同样的问题 . 我正在使用许多autorest服务客户端,但必须在每次传递用户特定客户端凭据的请求时重新实例化它们 . 使用Microsoft.Rest.ClientRuntime 2.3.6,您现在可以使用自己的HttpClient实例化ServiceClient . 这允许我使用具有单例HttpClient的瞬态ServiceClient . 我只是向生成的autorest客户端添加了一个新的构造函数 .

    public partial class MyClient : ServiceClient<IMyClient>, IMyClient
    {
    
        public MyClient(Uri baseUri, ServiceClientCredentials credentials, HttpClient client) : base(client)
        {
            if (baseUri == null)
            {
                throw new ArgumentNullException("baseUri");
            }
            if (credentials == null)
            {
                throw new ArgumentNullException("credentials");
            }
    
            this.Initialize();
            this.Credentials = credentials;
            Credentials?.InitializeServiceClient(this);
            this.BaseUri = baseUri;
    
        }
        [...]
    }
    

    但是,这会在第一个请求之后导致ObjectDisposedException . 这是因为ServiceClient处理HttpClients,无论您是否传入它 . method

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _disposed = true;
    
            // Dispose the client
            HttpClient.Dispose();
            HttpClient = null;
            FirstMessageHandler = null;
            HttpClientHandler = null;
        }
    }
    

    我只是覆盖了'MyClient'中的Dispose方法,什么都不做,因为唯一被处理的对象是HttpClient .

    protected override void Dispose(bool disposing) { }
    

    我没有发现任何后果,因为当ServiceClient为您创建HttpClient时,FirstMessageHandler和HttpClientHandler仅被实例化 . 这种方法允许我在多个AutoRest生成的ServiceClient上使用单个HttpClient,并在每个请求上使用自定义用户凭据 .

    我有兴趣看看是否有人看到这种方法有任何后果 .

  • 3

    您现在可以在ServiceClient的实例之间共享HttpClient实例,因此不再有很大的理由使用单例模式

相关问题