Using Singleton Instance inside Static method
我在Web应用程序中有一个静态方法调用。此方法使用其他类的单一实例。这个singleton实例基本上是一个用于发出一些API请求的httpclient。
目前,我没有任何机制来自动对其进行多用户测试。这种方法有什么后果吗?我知道,如果我们不在静态方法中使用静态变量,那么通常的静态方法是线程安全的。但我不知道在单身的情况下它是如何表现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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(); } |
为了避免线程问题,您至少需要以线程安全的方式实现单例。JonSkeet的这篇文章描述了如何以线程安全的方式创建单例实例。另外,您应该确保singleton的方法既可以处理并行请求,也可以使用
静态方法中使用单例的问题也是面向对象设计的问题之一。拥有一个单例并在应用程序的许多地方使用它是方便的,但也有其缺点:
- 其他开发人员看不到方法依赖于单例实例的第一个外观。这是一种隐藏的依赖关系。
- 此外,在需要不同行为的情况下(例如在测试中),您不能轻易地更改实例。
因此,我建议考虑单例是否真的是必要的,或者您是否可以将它作为参数注入到需要它的方法中:
1 2 3 4 5 6 7 8 9 | 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(); } |
您可以将方法更改为可调用的扩展方法,如下所示:
1 | var result = await API.Instance.GetData("123"); |
您只需在签名中添加一个
1 2 3 4 | public static async Task<string> GetData(this API api, string id) { // ... } |