¿Hay una manera sólida de registrar dependencias en ASP.NET Core 3.1 además de agregar todo a la clase de inicio?

9

Tengo un proyecto ASP.NET Core 3.1. Por lo general, registro cualquier dependencia utilizando el ConfigureServices()método en la Startup.csclase.

Pero, ¡me encuentro teniendo que registrar muchas dependencias y ConfigureServices()parece enorme! Sé que probablemente pueda crear un método de extensión de un método estático y llamarlo desde la clase ConfigureService () `, pero me pregunto si hay una mejor manera.

Si hay una forma de registrar dependencias en el contenedor de IoC sin tener que definirlas una a una como esta

services.AddScoped<Interface, Class>();
.... 200 lines later
services.AddScoped<ISettings, Settings>()

fuente

Respuestas:

10

Agrupar dependencias relacionadas en métodos de extensión personalizados es una forma muy común de hacerlo. ASP.NET Core ya hace esto para muchos de los servicios internos, y puede expandirse fácilmente además de eso y configurarlos de la manera que necesite para su aplicación. Por ejemplo, para configurar la autenticación y la autorización:

public IServiceCollection AddSecurity(this IServiceCollection services)
{
    services.AddAuthentication()
        .AddCookie();

    service.AddAuthorization(options =>
    {
        options.DefaultPolicy = …;
    });

    return services;
}

Puede hacer lo mismo para sus servicios específicos de la aplicación y agruparlos lógicamente en métodos de extensión separados.

Si tiene muchos registros de servicio que son muy similares, también puede emplear un registro basado en convenciones, por ejemplo, utilizando Scrutor . Por ejemplo, esto registra todos los servicios dentro de un determinado espacio de nombres como transitorios para su interfaz respectiva:

services.Scan(scan => scan
    .FromAssemblyOf<Startup>()
        .AddClasses(c => c.InNamespaces("MyApp.Services"))
            .AsImplementedInterfaces()
            .WithTransientLifetime()
);

Scrutor permite reglas muy complejas para buscar servicios, por lo que si sus servicios siguen algún patrón, es probable que pueda encontrar una regla para eso.

dar un toque
fuente
3

Crear un atributo personalizado (llamado AutoBindAttribute)

public class AutoBindAttribute : Attribute
{
}

Úselo como se indica a continuación (Decore todas las implementaciones que desea vincular automáticamente con [AutroBind])

public interface IMyClass {}

[AutoBind]
public class MyClass : IMyClass {}

Ahora cree un método de extensión para IServiceCollection

public class ServiceCollectionExtentions
{
    public static void AutoBind(this IServiceCollection source, params Assembly[] assemblies)
    {
       source.Scan(scan => scan.FromAssemblies(assemblies)
        .AddClasses(classes => classes.WithAttribute<AutoBindAttribute>())
        .AsImplementedInterfaces()
        .WithTransientLifetime();
    }
}

Ahora llámalo en Startup.cs

public class Startup
{

    public void ConfigureServices(IServiceCollection services)
    {
        services.AutoBind(typeof(Startup).Assembly);
    }

}

Nota: puede mejorar la ServiceCollectionExtentionsclase para admitir todos los ámbitos, como singleton, etc. Este ejemplo se muestra solo para la vida útil transitoria.

¡¡¡Disfrutar!!!

Dilhan Jayathilake
fuente
0

Además de lo mencionado.

Personalmente, me gusta tener una clase separada para registrar dependencias por cada ensamblado. Esto agrega más control sobre el uso de clases en la capa correcta y permite determinar internalcuál IMO es buena.

Si usar scanmecanismos o no depende de usted. Algunos marcos dan esto por defecto. Agrupar dependencias similares en un conjunto de clases / métodos, a su vez, debería ayudar a seguir resolviendo la lógica en un lugar consistente para cualquier cambio. Puedes combinar ambos enfoques.

Shymep
fuente