Esta sección fue evaluado por expertos para que tengas la garantía de la veracidad de este escrito.
Solución:
Hice una solución simple usando Func
cuando me encontré en esta situación.
En primer lugar, declare un delegado compartido:
public delegate IService ServiceResolver(string key);
Entonces en tu Startup.cs
, configure los múltiples registros concretos y un mapeo manual de esos tipos:
services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient(serviceProvider => key =>
switch (key)
case "A":
return serviceProvider.GetService();
case "B":
return serviceProvider.GetService();
case "C":
return serviceProvider.GetService();
default:
throw new KeyNotFoundException(); // or maybe return null, up to you
);
Y úsalo desde cualquier clase registrada con DI:
public class Consumer
private readonly IService _aService;
public Consumer(ServiceResolver serviceAccessor)
_aService = serviceAccessor("A");
public void UseServiceA()
_aService.DoTheThing();
Tenga en cuenta que en este ejemplo el key para la resolución es un string, en aras de la simplicidad y porque OP preguntaba por este caso en particular.
Pero podría usar cualquier tipo de resolución personalizada como key, ya que generalmente no desea que un gran cambio de n-case pudra su código. Depende de cómo escale su aplicación.
Otra opción es usar el método de extensión. GetServices
desde Microsoft.Extensions.DependencyInjection
.
Registra tus servicios como:
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
Luego resuelve con un poco de Linq:
var services = serviceProvider.GetServices();
var serviceB = services.First(o => o.GetType() == typeof(ServiceB));
o
var serviceZ = services.First(o => o.Name.Equals("Z"));
(asumiendo que IService
tiene un string propiedad llamada “Nombre”)
Asegúrate de tener using Microsoft.Extensions.DependencyInjection;
Actualizar
Fuente AspNet 2.1: GetServices
Simplemente inyecto un IEnumerable
Configurar servicios en Startup.cs
Assembly.GetEntryAssembly().GetTypesAssignableFrom().ForEach((t)=>
services.AddScoped(typeof(IService), t);
);
Carpeta de servicios
public interface IService
string Name get; set;
public class ServiceA : IService
public string Name get return "A";
public class ServiceB : IService
public string Name get return "B";
public class ServiceC : IService
public string Name get return "C";
MiControlador.cs
public class MyController
private readonly IEnumerable _services;
public MyController(IEnumerable services)
_services = services;
public void DoSomething()
var service = _services.Where(s => s.Name == "A").Single();
...
Extensiones.cs
public static List GetTypesAssignableFrom(this Assembly assembly)
return assembly.GetTypesAssignableFrom(typeof(T));
public static List GetTypesAssignableFrom(this Assembly assembly, Type compareType)
List ret = new List();
foreach (var type in assembly.DefinedTypes)
if (compareType.IsAssignableFrom(type) && compareType != type)
ret.Add(type);
return ret;
valoraciones y reseñas
Finalizando este artículo puedes encontrar las explicaciones de otros usuarios, tú de igual manera eres capaz mostrar el tuyo si lo deseas.