C# 除了将所有内容添加到Startup类中之外,是否还有一种健壮的方法可以在ASP.NET Core 3.1中注册依赖项?

C# 除了将所有内容添加到Startup类中之外,是否还有一种健壮的方法可以在ASP.NET Core 3.1中注册依赖项?,c#,asp.net-core,dependency-injection,asp.net-core-3.0,asp.net-core-3.1,C#,Asp.net Core,Dependency Injection,Asp.net Core 3.0,Asp.net Core 3.1,我有一个ASP.NETCore3.1项目。通常,我使用Startup.cs类中的ConfigureServices()方法注册任何依赖项 但是,我发现自己必须注册很多依赖项,而且ConfigureServices()看起来非常庞大!我知道我可能可以创建一个静态方法的扩展方法,并从ConfigureService()`类调用它,但不知道是否有更好的方法 如果有一种方法可以在IoC容器中注册依赖项,而不必像这样一次定义一个依赖项 services.AddScoped<Interface, Cl

我有一个ASP.NETCore3.1项目。通常,我使用
Startup.cs
类中的
ConfigureServices()
方法注册任何依赖项

但是,我发现自己必须注册很多依赖项,而且
ConfigureServices()
看起来非常庞大!我知道我可能可以创建一个静态方法的扩展方法,并从ConfigureService()`类调用它,但不知道是否有更好的方法

如果有一种方法可以在IoC容器中注册依赖项,而不必像这样一次定义一个依赖项

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

将相关依赖项分组到自定义扩展方法中是一种非常常见的方法。ASP.NET Core已经为许多内部服务实现了这一点,您可以轻松地在此基础上进行扩展,并按照应用程序所需的方式进行设置。例如,设置身份验证和授权:

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

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

    return services;
}
您可以对特定于应用程序的服务执行相同的操作,并在单独的扩展方法中对它们进行逻辑分组

如果您有许多非常相似的服务注册,您也可以使用基于约定的注册,例如使用。例如,这会将特定命名空间中的所有服务注册为其各自接口的瞬态服务:

services.Scan(scan => scan
    .FromAssemblyOf<Startup>()
        .AddClasses(c => c.InNamespaces("MyApp.Services"))
            .AsImplementedInterfaces()
            .WithTransientLifetime()
);
services.Scan(扫描=>Scan
.FromAssemblyOf()
.AddClasses(c=>c.InNamespaces(“MyApp.Services”))
.AsImplementedInterfaces()
.WithTransientLifetime()
);
Scrutor允许非常复杂的规则来扫描服务,因此,如果您的服务遵循某种模式,您很可能能够为此制定规则。

创建一个自定义属性(称为AutoBindAttribute)

像下面那样使用它(修饰所有要自动绑定到[AutroBind]的实现)

现在为IServiceCollection创建一个扩展方法

public static class ServiceCollectionExtensions
{
    public static void AutoBind(this IServiceCollection source, params Assembly[] assemblies)
    {
       source.Scan(scan => scan.FromAssemblies(assemblies)
        .AddClasses(classes => classes.WithAttribute<AutoBindAttribute>())
        .AsImplementedInterfaces()
        .WithTransientLifetime();
    }
}
注意:您可以改进
serviceCollectionExtensions
类以支持所有作用域,如单例等。此示例仅显示瞬时生存期


享受

除了刚才提到的以外

就我个人而言,我希望有一个单独的类为每个程序集注册依赖项。这增加了对在正确层使用类的更多控制,并允许将它们设置为
内部
,这是IMO的优点

是否使用
scan
机制取决于您。一些框架默认提供了这一点。反过来,将类似的依赖项分组到一组类/方法中,应该有助于将逻辑解析保持在任何更改的一致位置。您可以将这两种方法结合起来

public interface IMyClass {}

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

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

}