Llamar al constructor de la clase base explícitamente es la única forma de hacer esto usando la inyección de constructor en C#. Parece que debería eliminar los constructores sin parámetros de BaseController
y PublicController
, ya que nunca deberían llamarse cuando hay un registrador disponible.
El problema de inyectar dependencias en un controlador base es común con ASP.NET MVC e IoC. Hay varias opciones/escuelas de pensamiento.
1.) Utilice los servicios agregados. Para mantener simples a los constructores de clase derivados, cree un servicio único que exponga o delegue a todos los diferentes servicios necesarios para el controlador base (por ejemplo, IBaseControllerDependencies
o similar). Pase este servicio al BaseController
tal como lo hace con ILogger
aquí.
Existen varias ventajas y desventajas según su aplicación y la cantidad de clases base que esté utilizando.Google para 'servicios agregados Autofac' para ver más sobre esto.
2.) Utilice la inyección de propiedad. Hacer que la propiedad pública ILogger
en su clase base, y configurar el contenedor usando:
builder.RegisterControllers().PropertiesAutowired();
inyección de la propiedad no es realmente una técnica preferida en Autofac. El rol del constructor es para aceptar dependencias, mientras que las propiedades escribibles a menudo se ven como un olor a código, por lo que Autofac realmente no se optimiza para este caso. Uno de los inconvenientes es que las propiedades de escritura que no deberían inyectarse a menudo son erróneas, con consecuencias extrañas.
3.) Refactorizar la funcionalidad del controlador base en varios filtros de acción. Autofac puede inyectar filtros de acción en la canalización de invocación de acciones de MVC. Por lo tanto, los filtros pueden tomar las dependencias que estaban en la clase base, y las mismas preocupaciones podrían aplicarse de forma transversal. Más información al respecto en la web, ExtensibleActionInvoker
y .InjectActionInvoker()
apuntan a la información que necesitaría. No siempre es posible con todas las preocupaciones.
4, también la respuesta a su segunda pregunta.) Resuelva las dependencias del controlador base utilizando la ubicación del servicio desde DependencyResolver.Current
.
var logger = DependencyResolver.Current.GetService<ILogger>();
La razón de que esto no se anima es que hace que la aplicación resultante más difícil de entender, porque ya no es posible ver qué servicios un componente depende mirando en un solo lugar (el constructor). Para determinar lo que debe configurarse en el contenedor antes de que se pueda usar un componente en particular, hay que mirar toda la base de código del componente para encontrar las llamadas GetService()
. Un impedimento notable cuando pruebas unitarias.
Espero que esto ayude, un poco de un vertedero de cerebros que sé :) Otros probablemente puedan agregar algunas ideas más a estos.