简体   繁体   English

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

[英]Should we use Singletons for clients derived from Microsoft.Rest.ServiceClient in C#?

When working with Azure .NET SDKs generated from swagger specs (such as those associated with Azure Resource Manager) the resulting libraries leverage the Microsoft AutoRest Client Runtime and the various "Clients" all inherit from "ServiceClient". 使用swagger规范生成的Azure .NET SDK(例如与Azure Resource Manager关联的那些)时,生成的库利用Microsoft AutoRest Client Runtime,各种“Clients”都继承自“ServiceClient”。

We've been working with DocumentDB Client, and reading a lot about issues with using the native HttpClient in .NET. 我们一直在使用DocumentDB Client,并阅读了很多关于在.NET中使用本机HttpClient的问题。 Microsoft suggests using singleton patterns for both of these clients because of how they work internally, despite the well-known issues with using the singleton pattern. 尽管使用单例模式存在众所周知的问题,但Microsoft建议对这两个客户端使用单例模式,因为它们在内部工作。 In these cases, it is necessary. 在这些情况下,这是必要的。

As a result, we've developed a strategy for using and managing singletons for these cases, so we want to know if we should use the same strategy for the Azure REST clients derived from ServiceClient. 因此,我们为这些案例制定了使用和管理单例的策略,因此我们想知道是否应该对从ServiceClient派生的Azure REST客户端使用相同的策略。 If it uses HttpClient it would make sense. 如果它使用HttpClient,那将是有道理的。

Note: This question isn't a question looking for general developer advice about singletons or clients, but rather a specific question for the Microsoft dev teams associated with the AutoRest client runtime based on knowledge of it's inner-workings. 注意:这个问题不是寻找关于单身人士或客户的一般开发人员建议的问题,而是基于对其内部工作的了解而与AutoRest客户端运行时相关联的Microsoft开发团队的特定问题。

I've been trying to solve this same issue. 我一直试图解决同样的问题。 I'm using a number of autorest service clients, but have to re-instantiate them every request to pass user-specific client credentials. 我正在使用许多autorest服务客户端,但必须在每次传递用户特定客户端凭据的请求时重新实例化它们。 With Microsoft.Rest.ClientRuntime 2.3.6 you can now instantiate a ServiceClient with your own HttpClient. 使用Microsoft.Rest.ClientRuntime 2.3.6,您现在可以使用自己的HttpClient实例化ServiceClient。 This allows me to use a transient ServiceClient with a singleton HttpClient. 这允许我使用具有单例HttpClient的瞬态ServiceClient。 I simply added a new constructor to the generated autorest client. 我只是向生成的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;

    }
    [...]
}

This, however, would result in an ObjectDisposedException after the first request. 但是,这会在第一个请求之后导致ObjectDisposedException。 This is because the ServiceClient disposes HttpClients, regardless if you passed it in or not. 这是因为ServiceClient处理HttpClients,无论您是否传入它。 method 方法

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        _disposed = true;

        // Dispose the client
        HttpClient.Dispose();
        HttpClient = null;
        FirstMessageHandler = null;
        HttpClientHandler = null;
    }
}

I simply overrode the Dispose method in 'MyClient' to do nothing since the only object getting disposed is the HttpClient. 我只是覆盖了'MyClient'中的Dispose方法,什么都不做,因为唯一被处理的对象是HttpClient。

protected override void Dispose(bool disposing) { }

I haven't noticed any fallout from this as the FirstMessageHandler and HttpClientHandler are only instantiated when ServiceClient creates the HttpClient for you. 我没有发现任何后果,因为当ServiceClient为您创建HttpClient时,FirstMessageHandler和HttpClientHandler仅被实例化。 This approach has allowed me to use a single HttpClient across multiple AutoRest generated ServiceClients with custom user credentials on each request. 这种方法允许我在多个AutoRest生成的ServiceClient上使用单个HttpClient,并在每个请求上使用自定义用户凭据。

I'd be interested to see if anyone sees any fallout from this approach. 我有兴趣看看是否有人看到这种方法有任何后果。

Yes and no. 是的,不是。 :-) You don't need to use the Singleton design pattern, but it is advisable to share ServiceClient -derived instances wherever possible since each one encapsulates an HttpClient . :-)您不需要使用Singleton设计模式,但建议尽可能共享ServiceClient派生的实例,因为每个实例都封装了一个HttpClient

For some Azure libraries, sharing a single client isn't always possible. 对于某些Azure库,并不总是可以共享单个客户端。 For example, the SearchIndexClient in the Azure Search library can only target one index at a time, so if your app uses multiple indexes you'll need to pool them somehow. 例如, SearchIndexClient在Azure中搜索库只能指定一个索引的时间,因此,如果您的应用程序使用多个索引,你需要以某种方式汇集他们。 Here is a related question on this topic which has links to other discussions elsewhere. 以下是有关此主题的相关问题,该问题与其他地方的其他讨论有关。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM