我有一个自定义的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的最佳选择是什么?
答案 0 :(得分:0)
@Damien_The_Unbeliever:
由于我无法添加评论,因此我必须进行“完整答复”:
问题的方向是,当应用程序在Android设备上运行时,如何确保共享项目(既不是Android也不是iOS专用)中的HttpClient实例正确选择Android HttpClient
实现。< / p>