在Static方法中使用Singleton Instance

问题描述 投票:0回答:1

我在我的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个回答
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)
{
  // ...
}     
© www.soinside.com 2019 - 2024. All rights reserved.