Home > Software design >  Inject all class that implement and interface ASP.NET Core
Inject all class that implement and interface ASP.NET Core

Time:09-17

I have a base interface called IBaseService which I implement in many classes and I want to inject all classes that implement IBaseService.

Here is an example of my code:

public interface IBaseService
{
    Task<bool> Create();
}
    
public class EstadoService : IBaseService
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly IMapper _mapper;
    private readonly IRepository<Estado> _repository;
        
    public EstadoService()
    {
    }
        
    public EstadoService(IUnitOfWork unitOfWork, IMapper mapper, IRepository<Estado> repository)
    {
        _unitOfWork = unitOfWork;
        _mapper = mapper;
        _repository = repository;
    }
        
    public async Task<bool> Create()
    {
        // Create Logic
    } 
}
    
public static object AddServices(this IServiceCollection services)
{
 /*
   typeof(IBaseService).Assembly.GetTypes()                          
      .Where(mytype => mytype.GetInterface(typeof(IBaseService).Name) != 
       null).ToList().ForEach(appCoreService => 
       services.AddScoped(Activator.CreateInstance(appCoreService,)));
 */
    var items = typeof(IBaseService).Assembly.GetTypes()
                .Where(x => !x.IsAbstract && x.IsClass && 
         x.GetInterface(nameof(IBaseService)) == typeof(IBaseService));
            
     foreach (var item in items)
     {
         string _name = item.FullName;
         Type t = Type.GetType(_name);
                    
         var instance = (IBaseService) Activator.CreateInstance(t);
    
         services.Add(new ServiceDescriptor(typeof(IBaseService), instance, ServiceLifetime.Scoped));
     }
            
     return services;
}

public class EstadoController : BaseApiController
    {
        private readonly IEstadoService _estado;

        public EstadoController(IEstadoService estado)
        {
            _estado = estado;
        }

        [HttpPost("add-estado")]
        public async Task<ActionResult> AddEstado(EstadoRegisterDto registerEstadoDto)
        {
            await _estado.Create(registerEstadoDto);

            return Ok();
        }
    }

It looks fine, but it doesn't work.

CodePudding user response:

For the register operation, fix it a bit like this

// Register on Startup
var items = typeof(IBaseService).Assembly.GetTypes()
    .Where(x => !x.IsAbstract && x.IsClass && 
        x.GetInterface(nameof(IBaseService)) == typeof(IBaseService)).ToArray();

foreach (var item in items)
{
    services.Add(new ServiceDescriptor(typeof(IBaseService), item, ServiceLifetime.Scoped));
}

// Using
public IActionResult TestInjection([FromServices] IEnumerable<IBaseService> estadoService)
{
    // Place a debugger here to see the result
    var allImplementedServices = estadoService.ToArray();
}

CodePudding user response:

As I can see you just want to add services that inherit IBaseService interface to dependency injection.

In not dynamically scenario to add a service to dependency injection you have to do it like this:

services.AddScoped<IEstadoService, EstadoService>();

If you put it like this in your code this won't work because EstadoService does not implement IEstadoService and the class and interface are not related.

In your controller to access to the services your injecting IEstadoService so, to get this working the first you need to do is:

in IEstadoService inherit from IBaseService like this:

public interface IEstadoService: IBaseService 
{
    // code here...
}

and in EstadoService inherit from IEstadoService like this:

public class EstadoService: IEstadoService
{
    // code here...
}

in this case you can add dependency injection dynamically like this:

    public static object AddServices(this IServiceCollection services)
    {
        var list = Assembly.GetExecutingAssembly().GetTypes()
                .Where(mytype => mytype.GetInterface(typeof(IBaseService).Name) != null && !mytype.IsInterface)
                .ToList();

        foreach (var item in list)
        {
            services.AddScoped(item.GetInterface($"I{item.Name}"), item);
        }

        return services;
    }

The assembly list will have all services that inherit IBaseService in this case the list will have EstadoService.

As item in foreach loop is a Type we can call item.GetInterface($"I{item.Name}") which will result in interface object of type of IEstadoService

Like this it will work for all services that are implementing IBaseService

  • Related