Gibt es eine robuste Möglichkeit, Abhängigkeiten in ASP.NET Core 3.1 zu registrieren, außer alles zur Startup-Klasse hinzuzufügen?

9

Ich habe ein ASP.NET Core 3.1-Projekt. Normalerweise registriere ich jede Abhängigkeit mit der ConfigureServices()Methode in der Startup.csKlasse.

Aber ich muss viele Abhängigkeiten registrieren und das ConfigureServices()sieht riesig aus! Ich weiß, dass ich wahrscheinlich eine Erweiterungsmethode einer statischen Methode erstellen und sie aus der ConfigureService () `-Klasse aufrufen kann, frage mich aber, ob es einen besseren Weg gibt.

Wenn es eine Möglichkeit gibt, Abhängigkeiten im IoC-Container zu registrieren, ohne sie einzeln wie folgt definieren zu müssen

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

quelle

Antworten:

10

Das Gruppieren verwandter Abhängigkeiten in benutzerdefinierte Erweiterungsmethoden ist eine sehr häufige Methode, um dies zu tun. ASP.NET Core erledigt dies bereits für viele interne Dienste. Darüber hinaus können Sie diese problemlos erweitern und so einrichten, wie Sie es für Ihre Anwendung benötigen. Zum Einrichten der Authentifizierung und Autorisierung:

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

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

    return services;
}

Sie können dasselbe für Ihre anwendungsspezifischen Dienste tun und sie logisch in separaten Erweiterungsmethoden gruppieren.

Wenn Sie viele Serviceregistrierungen haben, die sehr ähnlich sind, können Sie auch eine konventionelle Registrierung verwenden, z . B. mit Scrutor . Dies registriert beispielsweise alle Dienste innerhalb eines bestimmten Namespace als vorübergehend für ihre jeweilige Schnittstelle:

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

Mit Scrutor können sehr komplexe Regeln nach Diensten durchsucht werden. Wenn Ihre Dienste also einem bestimmten Muster folgen , können Sie wahrscheinlich eine Regel dafür erstellen.

Sack
quelle
3

Erstellen Sie ein benutzerdefiniertes Attribut (AutoBindAttribute).

public class AutoBindAttribute : Attribute
{
}

Verwenden Sie es wie unten (Dekorieren Sie alle Implementierungen, die Sie automatisch mit [AutroBind] binden möchten).

public interface IMyClass {}

[AutoBind]
public class MyClass : IMyClass {}

Erstellen Sie nun eine Erweiterungsmethode für 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();
    }
}

Rufen Sie es jetzt in Startup.cs auf

public class Startup
{

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

}

Hinweis: Sie können die ServiceCollectionExtentionsKlasse verbessern , um alle Bereiche wie Singleton usw. zu unterstützen. Dieses Beispiel wird nur für die vorübergehende Lebensdauer angezeigt.

Genießen!!!

Dilhan Jayathilake
quelle
0

Neben dem, was erwähnt wurde.

Persönlich möchte ich eine separate Klasse haben, die Abhängigkeiten für jede Assembly registriert. Dies erhöht die Kontrolle über die Verwendung von Klassen auf der richtigen Ebene und ermöglicht es ihnen internal, festzustellen , welche IMO gut ist.

Ob Sie scanMechanismen verwenden oder nicht, liegt bei Ihnen. Einige Frameworks geben dies standardmäßig an. Das Gruppieren ähnlicher Abhängigkeiten in einer Reihe von Klassen / Methoden sollte wiederum dazu beitragen, die Logik für Änderungen an einem konsistenten Ort aufzulösen. Sie können beide Ansätze kombinieren.

Shymep
quelle