Есть ли способ синхронизировать доступ к синглтону на С#?C#

Место общения программистов C#
Ответить
Anonymous
 Есть ли способ синхронизировать доступ к синглтону на С#?

Сообщение Anonymous »

Я столкнулся с ситуацией при попытке запустить модульные тесты для синглтона. Я использую синглтон для управления одним HttpClient, который мое приложение может использовать для выполнения Http-запросов. Я знаю, что есть и другие способы сделать это, но в данный момент я работаю именно с этим подходом.
При нормальной работе с этим подходом проблем не возникает, поскольку HttpClient объект создается один раз и никогда не меняется на протяжении всего срока службы приложения. Проблема возникает, когда я пытаюсь запустить модульные тесты, поскольку я создаю несколько HttpClients, чтобы можно было имитировать их ответы.
Вот как в основном выглядит мой одноэлементный класс (это не реальный код, просто пример, демонстрирующий основную идею).

Код: Выделить всё

internal sealed class MySingleton
{
private static readonly Lazy _ instance = new Lazy(() => new MySingleton());

public static MySingleton Instance => _instance.Value;

private HttpClient _httpClient;

internal HttpClient HttpClient
{
get => _httpClient;
set //This is provided for testing, so I can mock the HttpMessageHandler
{
_httpClient = value;
}
}

private MySingleton()
{
SocketsHttpHandler
handler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(10)
};
_httpClient = new HttpClient(handler);
}

internal async Task SendRequest()
{
//Uses the HttpClient to send a request.
return true;
}
}
При этом всякий раз, когда моему приложению необходимо отправить Http-запрос, оно может просто вызвать await MySingleton.Instance.Send(). При нормальной работе это работает нормально.
Проблема возникает, когда я запускаю модульные тесты, поскольку они манипулируют HttpClient и выполняются параллельно. В настоящее время я заставляю тесты выполняться синхронно, но это не идеальное решение. Вот примерное представление о том, как выглядят мои тесты.

Код: Выделить всё

public class Tests
{
[Fact]
public async Task This_Is_A_Test()
{
string
jsonText = """
{
"id" : 1,
"name" : "testing",
"value" : 23
}
""";
HttpMessageHandler
httpMessageHandler = new MockHttpMessageHandler(jsonText, System.Net.HttpStatus.Created);
MySingleton.Instance.HttpClient = new HttpClient(httpMessageHandler);

bool
result = await MySingleton.Instance.SendRequest();
Assert.IsTrue(result);
}
}
Объект MockHttpMessageHandler — это всего лишь написанный мной класс, который расширяет класс HttpMessageHandler, поэтому я могу манипулировать ответом HttpClient.
Как видно из тестового кода, я заменяю HttpClient в синглтоне на тот, который будет возвращать нужные мне данные. Побочным эффектом этого является сбой тестов, когда они выполняются параллельно.
Мне интересно, есть ли способ синхронизировать доступ к экземпляру синглтона, поэтому что он может использоваться только одним потоком одновременно. По сути, поток захватывает синглтон, использует его по назначению, а затем отпускает обратно для использования другим потоком.
Возможно, мой подход здесь совершенно неправильный, и в этом случае я Я открыт для предложений. Хотя мне бы очень хотелось знать, возможно ли сделать то, что я пытаюсь сделать. Я пытался найти ответ в Google, но придумал только синхронизацию создания экземпляра (который Lazy уже обрабатывает). Я даже пробовал использовать ИИ, но это не помогло.

Подробнее здесь: https://stackoverflow.com/questions/791 ... leton-in-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»