简体   繁体   中英

C# .net core - dependency injection reference to memorycache

In order to store an Oauth token in MemoryCache (.net core 3.1 API) - I found the below example (some parts left out) but I can't find a way call the constructor of the HTTPservice so it uses the memorycache.

First there's an interface definition:

    public interface ITokenService
    {
        string FetchToken();
    }

Then the interface implementation

 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";
        }
    }

Then the memorycache and TokenService is added in startup.cs

   services.AddMemoryCache();
   services.AddSingleton<ITokenService, TokenService>();

Lastly a HTTPservice that will use the token from cache is implemented like this:

 public class HttpService
    {
        private ITokenService token;

        public HttpService(ITokenService token)
        {
            this.token = token;
        }

        public string GetReadersFromExternalApi(string requestUrl)
        {
            return token.FetchToken();
        }
    }

problem described here

To use the HTTPService the constructor has to be called - but the constructor expects a TokenService as parameter, and the TokenService expects IMemoryCache in the constructor.

So i tried this line of code to make a new HTTPservice object, but cache is empty on consecutive calls - so what parameters should be passed to the constructor in order to reference the tokenservice/memorycache?

var httpService 
    = new HttpService(new TokenService(new MemoryCache(new MemoryCacheOptions())));

I think you have 2 ways to solve this:

Solution A

Inject your HttpService as scoped (instance per request) which will have the single TokenService instance and should work fine.

services.AddScoped<HttpService>();

Solution B

You may could create an instance of the HttpService by constructor but in that case you should inject the ITokenService in the same service where HttpService is being created, and pass it as parameter.

public class SomeClass 
{
    private readonly ITokenService _tokenService;

    public SomeClass(ITokenService tokenService)
    {
        _tokenService = tokenService;
    }

    public HttpService CreateHttpService()
    {
        return new HttpService(_tokenService);
    }
}

I would go with the first solution, but I include the second one because may be useful for you to understand the issue

Your code here creates a new MemoryCache every time the code is called, that means that a new cache is being created so when this code runs a second time it will use a different empty cahce than the first execution. Which is why the cache is empty.

HttpService httpService = new HttpService(new TokenService(new MemoryCache(new MemoryCacheOptions())));

Where you configure your dependency injection, you should add the following line to register your HttpService as a new dependency

services.AddSingleton<IHttpService, HttpService>();

*Note that this line will require you adding in a new IHttpService which HttpService implements.

Then wherever you need to access the HttpService , you should inject the new IHttpService and let the dependency injection contain handle everything else.

For example:

public class MyService
{
    private readonly IHttpService _httpService { get; set; }
    public MyService(IHttpService httpService)
    {
        _httpService = httpService;
    }

    public void MyMethod()
    {
        var readers = _httpService.GetReadersFromExternalApi("Example Request");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM