Search code examples
c#.net.net-coredependency-injection

How to register class using multi-level inheritance with interface


In my .NET Core 8 API having interfaces like these:-

// Interfaces

public interface ITokenService { 
   string Generate(UserDetail user);
}

public interface IAccessTokenService : ITokenService { }

public interface IRefreshTokenService : ITokenService { }
      
}
    

RefreshTokenService class:-

public class RefreshTokenService : IRefreshTokenService { 

       private readonly ITokenGenerator _tokenGenerator;
 private readonly JWTSettings _jwtSettings;
 public RefreshTokenService(IOptions<JWTSettings> settings, ITokenGenerator tokenGenerator)
 => (_tokenGenerator, _jwtSettings) = (tokenGenerator, settings.Value);

 public string Generate(UserDetail user) => _tokenGenerator.Generate(_jwtSettings.RefreshTokenSecret, _jwtSettings.Issuer, _jwtSettings.Audience, _jwtSettings.RefreshTokenExpiry);
}

AccessTokenService class:-

   public class AccessTokenService : IAccessTokenService
   {
      private readonly ITokenGenerator _tokenGenerator;
      private readonly JWTSettings _jwtSettings;
      public AccessTokenService(ITokenGenerator tokenGenerator, JWTSettings jwtSettings) =>
             (_tokenGenerator, _jwtSettings) = (tokenGenerator, jwtSettings);
    
    public string Generate(UserDetail user)
    {
        List<Claim> claims = new List<Claim>() {};

        return _tokenGenerator.Generate(_jwtSettings.AccessTokenSecret, _jwtSettings.Issuer, _jwtSettings.Audience, _jwtSettings.RefreshTokenExpiry,claims);
    }
}

And I have registered these classes in Statup.cs

services.AddScoped<ITokenService, RefreshTokenService>();
services.AddScoped<ITokenService, AccessTokenService>();

services.AddTransient<IAccessTokenService, AccessTokenService>();
services.AddTransient<IRefreshTokenService, RefreshTokenService>(); 
--------------Other services here---------------

Service class where I am using access token and refresh token classes

public class SomeClass : ISomeService{
    private readonly IRefreshTokenService _refreshTokenService;
    private readonly IAccessTokenService _accessTokenService;
    
     public SomeClass(IRefreshTokenService refreshTokenService, 
      IAccessTokenService accessTokenService){
           _refreshTokenService =  refreshTokenService;
           _accessTokenService = accessTokenService;
      }
}

But getting error:

Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: API.Services.IAccessTokenService Lifetime: Transient ImplementationType: Services.AccessTokenService': Unable to resolve service for type 'Models.JWTSettings' while attempting to activate 'Services.AccessTokenService`. How to resolve depencency here.


Solution

  • It seems that are using the options pattern for your configuration then you need to resolve one for the IOptions...<TOptions> interfaces, usually IOptions<TOptions> itself instead of directly resolving the configuration class. For example:

    public AccessTokenService(ITokenGenerator tokenGenerator, IOptions<JWTSettings> jwtSettingsOpts) =>
         (_tokenGenerator, _jwtSettings) = (tokenGenerator, jwtSettingsOpts.Value);
    

    Note that in RefreshTokenService you are doing exactly that:

    public RefreshTokenService(IOptions<JWTSettings> settings, ITokenGenerator tokenGenerator) 
    => (_tokenGenerator, _jwtSettings) = (tokenGenerator, settings.Value);