Esiste un modo affidabile per registrare le dipendenze in ASP.NET Core 3.1 oltre ad aggiungere tutto nella classe Startup?


9

Ho un progetto ASP.NET Core 3.1. In genere, registro qualsiasi dipendenza usando il ConfigureServices()metodo nella Startup.csclasse.

Ma mi ritrovo a dover registrare molte dipendenze e l' ConfigureServices()aspetto è enorme! So che probabilmente posso creare un metodo di estensione di un metodo statico e chiamarlo dalla classe ConfigureService () `, ma mi chiedo se esiste un modo migliore.

Se esiste un modo per registrare le dipendenze nel contenitore IoC senza doverle definire una alla volta in questo modo

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

Risposte:


10

Raggruppare le dipendenze correlate in metodi di estensione personalizzati è un modo molto comune per farlo. ASP.NET Core lo fa già per molti dei servizi interni e puoi facilmente espanderci e configurarli nel modo che ti serve per la tua applicazione. Ad esempio per impostare l'autenticazione e l'autorizzazione:

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

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

    return services;
}

Puoi fare lo stesso per i tuoi servizi specifici dell'applicazione e raggrupparli logicamente in metodi di estensione separati.

Se disponi di molte registrazioni di servizi molto simili, puoi anche utilizzare una registrazione basata su una convenzione, ad esempio utilizzando Scrutor . Ad esempio, questo registra tutti i servizi all'interno di un determinato spazio dei nomi come transitori per la rispettiva interfaccia:

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

Scrutor consente regole molto complesse per la ricerca di servizi, quindi se i tuoi servizi seguono un certo schema, probabilmente sarai in grado di trovare una regola per questo.


3

Crea un attributo personalizzato (chiamato AutoBindAttribute)

public class AutoBindAttribute : Attribute
{
}

Usalo come qui sotto (Decora tutte le implementazioni che vuoi associare automaticamente con [AutroBind])

public interface IMyClass {}

[AutoBind]
public class MyClass : IMyClass {}

Ora crea un metodo di estensione per 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();
    }
}

Ora chiamalo in Startup.cs

public class Startup
{

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

}

Nota: è possibile migliorare la ServiceCollectionExtentionsclasse per supportare tutti gli ambiti come singleton, ecc. Questo esempio mostra solo la durata del transiente.

Godere!!!


0

Oltre a quanto menzionato.

Personalmente mi piace avere una classe separata che registra le dipendenze per ogni assieme. Ciò aggiunge un maggiore controllo sull'utilizzo delle classi al livello giusto e consente di stabilire internalquale IMO è efficace.

Se usare i scanmeccanismi o meno dipende da te. Alcuni framework forniscono questo per impostazione predefinita. Il raggruppamento di dipendenze simili in un insieme di classi / metodi, a sua volta, dovrebbe aiutare a mantenere la logica di risoluzione in un luogo coerente per eventuali modifiche. È possibile combinare entrambi gli approcci.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.