我有一个自定义的HttpClient实现,需要从配置中获取一些值才能正常工作。
public class MyHttpClient : HttpClient
{
public MyHttpClient()
{
}
public MyHttpClient(string token)
{
Token = token;
}
public string Token { get; set; }
// ...
}
现在,我想在使用
IOptions<TOptions>
进行配置的应用程序逻辑中使用此HttpClient。public class MyLogic
{
private static MyHttpClient Client;
public MyLogic(IOptions<MyConfig> config)
{
// How to instantiate Client with values from config?
}
}
因为HttpClient should be held as a static field,所以我无法将config值注入HttpClient中。我想出了几种可能性,但似乎都没有。
选项1:每次设置配置值
public class MyLogic
{
private static MyHttpClient Client = new MyHttpClient();
public MyLogic(IOptions<MyConfig> config)
{
Client.Token = config.Value.Token;
}
}
这似乎是最糟糕的选择,因为
Token
的值可能会随着HttpClient使用它而改变。选项2:每次锁定
public class MyLogic
{
private static MyHttpClient Client;
private static readonly object ClientLock = new object();
public MyLogic(IOptions<MyConfig> config)
{
lock(ClientLock)
{
if (Client == null)
{
Client = new MyHttpClient(config.Value.Token);
}
}
}
}
从性能的角度看,这似乎是不好的,因为
MyLogic
的每个实例都将创建一个锁并阻塞所有其他锁。选项3:双重检查锁定
public class MyLogic
{
private static volatile MyHttpClient Client;
private static readonly object ClientLock = new object();
public MyLogic(IOptions<MyConfig> config)
{
if (Client == null)
{
lock(ClientLock)
{
if (Client == null)
{
Client = new MyHttpClient(config.Value.Token);
}
}
}
}
}
这似乎是解决方案,但是很难正确检查双重检查的锁,因此应避免使用。
可悲的是,Lazy<T>似乎不是一个选择,因为它还需要静态上下文来创建实例。
那么,在这种情况下实例化HttpClient的最佳选择是什么?
最佳答案
@Damien_The_Unbeliever:
由于我无法添加评论,因此我必须进行“完整答复”:
问题的方向是,当应用程序在Android设备上运行时,如何确保共享项目(既不是Android也不是iOS)中的HttpClient实例正确选择Android HttpClient
实现。
关于c# - 如何在构造函数中正确实例化静态HttpClient,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52761164/