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