¿Cómo resuelvo manualmente un tipo usando el marco de inyección de dependencia incorporado ASP.NET Core MVC?
Configurar el contenedor es bastante fácil:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddTransient<ISomeService, SomeConcreteService>();
}
Pero, ¿cómo puedo resolver ISomeServicesin realizar la inyección? Por ejemplo, quiero hacer esto:
ISomeService service = services.Resolve<ISomeService>();
No hay tales métodos en IServiceCollection.

ConfigureServices()método (conIServiceCollection) o en cualquier lugar de la aplicación?Respuestas:
La
IServiceCollectioninterfaz se usa para construir un contenedor de inyección de dependencia. Una vez que está completamente construido, se compone de unaIServiceProviderinstancia que puede usar para resolver servicios. Puede inyectar unIServiceProvideren cualquier clase. LosIApplicationBuilderyHttpContextlas clases pueden proporcionar el proveedor de servicio, así, a través de susApplicationServicesoRequestServicespropiedades respectivamente.IServiceProviderdefine unGetService(Type type)método para resolver un servicio:También hay varios métodos de extensión de conveniencia disponibles, como
serviceProvider.GetService<IFooService>()(agregar unusingparaMicrosoft.Extensions.DependencyInjection).Resolviendo servicios dentro de la clase de inicio
Inyectando dependencias
Proveedor de alojamiento de servicio del tiempo de ejecución puede inyectar ciertos servicios en el constructor de la
Startupclase, tales comoIConfiguration,IWebHostEnvironment(IHostingEnvironmenten pre-3.0 versiones),ILoggerFactoryyIServiceProvider. Tenga en cuenta que esta última es una instancia creada por la capa de alojamiento y contiene solo los servicios esenciales para iniciar una aplicación .El
ConfigureServices()método no permite inyectar servicios, solo acepta unIServiceCollectionargumento. Esto tiene sentido porqueConfigureServices()es donde registra los servicios requeridos por su aplicación. Sin embargo, puede utilizar los servicios inyectados en el constructor de la startup aquí, por ejemplo:Cualquier servicio registrado en
ConfigureServices()puede ser inyectado en elConfigure()método; Puede agregar un número arbitrario de servicios después delIApplicationBuilderparámetro:Resolver dependencias manualmente
Si necesita resolver los servicios de forma manual, debe utilizar preferiblemente el
ApplicationServicesproporcionado porIApplicationBuilderen elConfigure()método:Es posible pasar y usar directamente un
IServiceProvideren el constructor de suStartupclase, pero como se indica arriba , contendrá un subconjunto limitado de servicios y, por lo tanto, tiene una utilidad limitada:Si debe resolver los servicios en el
ConfigureServices()método, se requiere un enfoque diferente. Puede crear un intermediarioIServiceProviderdesde laIServiceCollectioninstancia que contiene los servicios que se han registrado hasta ese momento :Tenga en cuenta: en general, debe evitar resolver servicios dentro del
ConfigureServices()método, ya que este es realmente el lugar donde está configurando los servicios de la aplicación. A veces solo necesitas acceder a unaIOptions<MyOptions>instancia. Puede lograr esto vinculando los valores de laIConfigurationinstancia a una instancia deMyOptions(que es esencialmente lo que hace el marco de opciones):La resolución manual de servicios (también conocido como Localizador de servicios) generalmente se considera un antipatrón . Si bien tiene sus casos de uso (para marcos y / o capas de infraestructura), debe evitarlo tanto como sea posible.
fuente
IServiceCollectioninyectado, alguna clase que se está creando manualmente ( fuera del alcance del software intermedio ), un planificador en mi caso, que periódicamente necesita algunos servicios para generar y enviar un correo electrónicoConfigureServicesy ese servicio es un singleton, ¡será un singleton diferente al queControllerusa! Supongo que esto se debe a que utiliza una diferenteIServiceProvider- para evitar esto no se resuelve a través deBuildServiceProvidery en lugar de mover su operaciones de búsqueda del singleton deConfigureServicesqueConfigure(..other params, IServiceProvider serviceProvider)enStartup.csIServiceProviderinstancia diferente , creará una nueva instancia de singleton. Puede evitar esto devolviendo la instancia del proveedor de servicios delConfigureServicesmétodo, de modo que también será el contenedor que usa su aplicación.collection.BuildServiceProvider();era lo que necesitaba, ¡gracias!La resolución manual de instancias implica el uso de la
IServiceProviderinterfaz:Resolviendo dependencia en Startup.ConfigureServices
Resolver dependencias en el inicio.
Resolver dependencias en el inicio.Configurar en ASP.NET Core 3
Uso de servicios inyectados en tiempo de ejecución
Algunos tipos se pueden inyectar como parámetros de método:
Resolver dependencias en acciones del controlador
fuente
GetServiceque es genérico, es un método de extensión en elMicrosoft.Extensions.DependencyInjectionespacio de nombres.Si genera una aplicación con una plantilla, tendrá algo como esto en la
Startupclase:Luego puede agregar dependencias allí, por ejemplo:
Si desea acceder
ITestServiceen su controlador, puede agregarIServiceProviderel constructor y se inyectará:Luego puede resolver el servicio que agregó:
Tenga en cuenta que para usar la versión genérica debe incluir el espacio de nombres con las extensiones:
ITestService.cs
TestService.cs
Startup.cs (ConfigureServices)
HomeController.cs
fuente
Si solo necesita resolver una dependencia con el fin de pasarla al constructor de otra dependencia que está registrando, puede hacerlo.
Digamos que tenía un servicio que incluía una cadena y un ISomeService.
Cuando vaya a registrar esto dentro de Startup.cs, deberá hacer esto:
fuente
ISomeServicetodavía era nulo para mí.Puede inyectar dependencias en atributos como AuthorizeAttribute de esta manera
fuente
Sé que esta es una vieja pregunta, pero me sorprende que no haya un truco bastante obvio y desagradable.
Puede aprovechar la capacidad de definir su propia función de ctor para tomar los valores necesarios de sus servicios a medida que los define ... obviamente, esto se ejecutará cada vez que se solicite el servicio a menos que elimine / borre explícitamente y vuelva a agregar la definición de Este servicio dentro de la primera construcción del ctor explotador .
Este método tiene la ventaja de no requerir que construya el árbol de servicios o que lo use durante la configuración del servicio. Todavía está definiendo cómo se configurarán los servicios.
La forma de arreglar este patrón sería dar
OtherServiceuna dependencia explícitaIServiceINeedToUse, en lugar de depender implícitamente de él o del valor de retorno de su método ... o resolver esa dependencia explícitamente de alguna otra manera.fuente
fuente