#c# #.net-core #dependency-injection #dependencies
Вопрос:
Чтобы сохранить токен Oauth в кэше памяти (API .net core 3.1) — я нашел приведенный ниже пример (некоторые части опущены), но я не могу найти способ вызвать конструктор HTTPService, поэтому он использует кэш памяти.
Во-первых, есть определение интерфейса:
public interface ITokenService
{
string FetchToken();
}
Затем реализация интерфейса
public class TokenService : ITokenService
{
private readonly IMemoryCache cache;
public TokenService(IMemoryCache cache)
{
this.cache = cache;
}
public string FetchToken()
{
string token = string.Empty;
if (!cache.TryGetValue("TOKEN", out token))
{
var tokenValue = this.GetTokenFromApi();
var options = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(
TimeSpan.FromSeconds(3600));
cache.Set("TOKEN", tokenValue, options);
token = tokenValue;
}
return token;
}
private string GetTokenFromApi()
{
return "Test";
}
}
Затем в startup.cs добавляется кэш памяти и сервис токенов
services.AddMemoryCache();
services.AddSingleton<ITokenService, TokenService>();
Наконец, HTTPService, который будет использовать токен из кэша, реализован следующим образом:
public class HttpService
{
private ITokenService token;
public HttpService(ITokenService token)
{
this.token = token;
}
public string GetReadersFromExternalApi(string requestUrl)
{
return token.FetchToken();
}
}
проблема, описанная здесь
Для использования HTTPService
конструктора должен быть вызван — но конструктор ожидает в качестве параметра службу TokenService, и TokenService
ожидает IMemoryCache
в конструкторе.
Поэтому я попробовал эту строку кода, чтобы создать новый HTTPservice
объект, но кэш пуст при последовательных вызовах — так какие параметры следует передать конструктору, чтобы ссылаться на tokenservice/memorycache?
var httpService
= new HttpService(new TokenService(new MemoryCache(new MemoryCacheOptions())));
Комментарии:
1. Вам необходимо зарегистрировать свой HTTPService в вашей инъекции dependecy:
services.AddSingleton<IHttpService, HttpService>();
сначала вам нужно будет создатьIHttpService
интерфейс. Затем вы можете ввестиIHttpService
в конструктор класса, из которого вы его вызываете2. Вы добавили
https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/
посылку?
Ответ №1:
Я думаю, что у вас есть 2 способа решить эту проблему:
Решение А
Введите свой HTTPService в область действия (экземпляр на запрос), который будет иметь один экземпляр TokenService и должен работать нормально.
services.AddScoped<HttpService>();
Решение В
Вы можете создать экземпляр HTTPService с помощью конструктора, но в этом случае вам следует внедрить ITokenService в ту же службу, где создается HTTPService, и передать его в качестве параметра.
public class SomeClass
{
private readonly ITokenService _tokenService;
public SomeClass(ITokenService tokenService)
{
_tokenService = tokenService;
}
public HttpService CreateHttpService()
{
return new HttpService(_tokenService);
}
}
Я бы выбрал первое решение, но я включаю второе, потому что оно может быть полезно для вас, чтобы понять проблему
Ответ №2:
Ваш код здесь создает новый MemoryCache
каждый раз при вызове кода, это означает, что создается новый кэш, поэтому при повторном запуске этого кода он будет использовать другой пустой cahce, чем при первом выполнении. Вот почему кэш пуст.
HttpService httpService = new HttpService(new TokenService(new MemoryCache(new MemoryCacheOptions())));
При настройке внедрения зависимостей следует добавить следующую строку для регистрации службы HTTPService в качестве новой зависимости
services.AddSingleton<IHttpService, HttpService>();
*Обратите внимание, что эта строка потребует от вас добавления новой IHttpService
, которая HttpService
реализует.
Затем везде , где вам нужно получить доступ HttpService
, вы должны ввести новое IHttpService
и позволить инъекции зависимостей обрабатывать все остальное.
Например:
public class MyService
{
private readonly IHttpService _httpService { get; set; }
public MyService(IHttpService httpService)
{
_httpService = httpService;
}
public void MyMethod()
{
var readers = _httpService.GetReadersFromExternalApi("Example Request");
}
}
Комментарии:
1. Это сработает! Это решило проблему — похоже, мне придется немного почитать о внедрении зависимостей….