【问题标题】:Using Singleton Instance inside Static method在静态方法中使用单例实例
【发布时间】:2019-02-20 08:54:10
【问题描述】:

我在我的 Web 应用程序中调用了一个静态方法。此方法使用不同类的单例实例。这个单例实例基本上是一个 HttpClient 来发出一些 api 请求。

目前我没有任何机制来自动化多用户测试。这种方法有什么后果吗?我知道如果我们不在其中使用静态变量,通常的静态方法是线程安全的。但我不确定它在单例情况下的表现。

public static class API
{
    private static System.Net.Http.HttpClient httpClient;

    public static System.Net.Http.HttpClient Instance
    {
        get
        {
            return httpClient ?? (httpClient = new System.Net.Http.HttpClient());
        }
    }
}

public static async Task<string> GetData(string id)
{
    HttpResponseMessage response = await 
    API.Instance.GetAsync(string.Format(requestURL, id));
    response.EnsureSuccessStatusCode();

    // return URI of the created resource.
    return await response.Content.ReadAsStringAsync();
}

【问题讨论】:

标签: c# .net static thread-safety singleton


【解决方案1】:

为了避免线程问题,您至少需要以线程安全的方式实现单例。 Jon Skeet 的 article 描述了一些如何以线程安全的方式创建单例实例的方法。此外,您应该确保单例的方法可以处理并行请求或使用lock 来同步调用。

在静态方法中使用 Singleton 的问题也是面向对象设计的问题之一。拥有一个单例并在应用程序的许多地方使用它很方便,但也有其缺点:

  • 一位开发人员第一眼看不到您的方法依赖于单例实例。这是一个隐藏的依赖。
  • 此外,在需要不同行为的情况下,您不能轻易更改实例,例如在测试中。

所以我建议考虑一下单例是否真的有必要,或者你是否可以将它作为参数注入到需要它的方法中:

public static async Task<string> GetData(API api, string id)
{
    HttpResponseMessage response = await 
    api.Instance.GetAsync(string.Format(requestURL, id));
    response.EnsureSuccessStatusCode();

    // return URI of the created resource.
    return await response.Content.ReadAsStringAsync();
}

您可以将方法更改为可以调用的扩展方法:

var result = await API.Instance.GetData("123");

您只需在签名中添加this

public static async Task<string> GetData(this API api, string id)
{
  // ...
}     

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多