Saltar al contenido

Inyección de propiedades en ASP.NET Core

Solución:

No, el contenedor DI / IoC integrado se mantiene intencionalmente simple tanto en uso como en funciones para ofrecer una base para que otros contenedores DI se conecten.

Por lo tanto, no hay soporte integrado para: descubrimiento automático, registros automáticos, decoradores o inyectores, o registros basados ​​en convenciones. Tampoco hay planes para agregar esto al contenedor incorporado hasta donde yo sé.

Tendrá que usar un contenedor de terceros con soporte de inyección de propiedad.

Tenga en cuenta que la inyección de propiedades se considera mala en el 98% de todos los escenarios, porque oculta las dependencias y no hay garantía de que el objeto se inyecte cuando se cree la clase.

Con la inyección del constructor, puede hacer cumplir esto a través del constructor y verificar si hay nulo y no crear la instancia de la clase. Con la inyección de propiedades, esto es imposible y durante las pruebas unitarias no es obvio qué servicios / dependencias requiere la clase cuando no están definidos en el constructor, por lo que es fácil perderlos y obtenerlos. NullReferenceExceptions.

La única razón válida para la inyección de propiedades que encontré fue para inyectar servicios en clases de proxy generadas por una biblioteca de terceros, es decir, proxies WCF creados a partir de una interfaz en la que no tienes control sobre la creación del objeto. E incluso allí, es solo para bibliotecas de terceros. Si genera Proxies WCF usted mismo, puede extender fácilmente la clase de proxy a través de partial class y agregue un nuevo constructor, métodos o propiedades compatibles con DI.

Evítalo En todas partes demás.

¿Hay alguna forma de lograr la misma funcionalidad usando DI integrado en .NET Core?

No, pero así es como puede crear su propio [inject] atributos con la ayuda del mecanismo de inyección de propiedades de Autofac.

Primero crea el tuyo InjectAttribute:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InjectAttribute : Attribute
{
  public InjectAttribute() : base() { }
}

Entonces crea el tuyo propio InjectPropertySelector que utiliza la reflexión para comprobar las propiedades marcadas con [inject]:

public class InjectPropertySelector : DefaultPropertySelector
{
  public InjectPropertySelector(bool preserveSetValues) : base(preserveSetValues)
  { }

  public override bool InjectProperty(PropertyInfo propertyInfo, object instance)
  {
    var attr = propertyInfo.GetCustomAttribute<InjectAttribute>(inherit: true);
    return attr != null && propertyInfo.CanWrite
            && (!PreserveSetValues
            || (propertyInfo.CanRead && propertyInfo.GetValue(instance, null) == null));
  }
}

Luego use su selector en su ConfigureServices donde conectas tu AutofacServiceProvider:

public class Startup
{
  public IServiceProvider ConfigureServices(IServiceCollection services)
  {
    var builder = new ContainerBuilder();
    builder.Populate(services);
    
    // use your property selector to discover the properties marked with [inject]
    builder.RegisterType<MyServiceX>().PropertiesAutowired((new InjectablePropertySelector(true)););

    this.ApplicationContainer = builder.Build();
    return new AutofacServiceProvider(this.ApplicationContainer);
  }
}

Finalmente en su servicio ahora puede usar [inject]:

public class MyServiceX 
{
    [Inject]
    public IOrderRepository OrderRepository { get; set; }
    [Inject]
    public ICustomerRepository CustomerRepository { get; set; }
}

Seguramente puede llevar esta solución aún más lejos, por ejemplo, utilizando un atributo para especificar el ciclo de vida de su servicio por encima de la definición de clase de su servicio …

[Injectable(LifetimeScope.SingleInstance)]
public class IOrderRepository

… y luego verificar este atributo al configurar sus servicios a través de Autofac. Pero esto iría más allá del alcance de esta respuesta.

Es compatible con .Nurse Injector: https://github.com/enisn/DotNurseInjector#propertyfield-injection

Puedes hacerlo en 3 pasos:

  • Paquete de instalación DotNurse.Injector.AspNetCore
  • Llame al siguiente método al Program.cs
 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseDotNurseInjector() // <-- Add this method
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
  • Entonces puedes usar [InjectService] atributo en lugar de inyección de constructor:
[InjectService] public IBookRepository BookRepository { get; set; }
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *