Как правильно создать экземпляр статического HttpClient в конструкторе - PullRequest
0 голосов
/ 11 октября 2018

У меня есть пользовательская HttpClient реализация, для работы которой требуются некоторые значения из моей конфигурации.

public class MyHttpClient : HttpClient
{
    public MyHttpClient()
    {
    }

    public MyHttpClient(string token)
    {
        Token = token;
    }

    public string Token { get; set; }

    // ...
}

Теперь я хочу использовать этот HttpClient в моей логике приложения, которая использует IOptions<TOptions> для получения его конфигурации.

public class MyLogic
{
    private static MyHttpClient Client;

    public MyLogic(IOptions<MyConfig> config)
    {
        // How to instantiate Client with values from config?
    }
}

Поскольку HttpClient должен храниться как статическое поле , я борюсь с методом, которым я могу ввести значение конфигурации в 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 не представляется возможным, поскольку для этого также требуется статический контекст, напримерсоздание.

Итак, что будет лучшим вариантом для создания экземпляра HttpClient в этой ситуации?

1 Ответ

0 голосов
/ 18 июля 2019

@ Damien_The_Unbeliever:

Поскольку я не могу добавить комментарий, я должен сделать «полный ответ»: вопрос идет в направлении того, как я могу убедиться, что экземпляр HttpClient внутри общего ресурсаПроект (который не относится ни к Android, ни к iOS) правильно выбирает реализацию Android HttpClient, когда приложение работает на устройстве Android.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...