具有约定的内置依赖项注入

SHM*_*SHM 5 c# dependency-injection asp.net-core

如何在不注册服务的情况下注入服务?我的意思是,过去有些DI框架自动注册ServiceIService

我处于一种状态,那里我有很多服务,而基本上每一个服务都很难注册。所以在asp.net核心默认DI框架中支持此功能吗?

che*_*ets 7

我想您喜欢Autofac的工作方式:

var assembly = typeof(MyModule).Assembly;
builder.RegisterAssemblyTypes(assembly)
    .Where(t => t.Name.EndsWith("Service"))
    .AsImplementedInterfaces()
    .InstancePerLifetimeScope();
Run Code Online (Sandbox Code Playgroud)

但是由于某些原因,您不想切换到Autofac(例如,您想使用来自外部库的扩展来注册其依赖项)。所以我的建议是创建一些使用反射的扩展,例如:

public static IServiceCollection AddSingletonsByConvention(this IServiceCollection services, Assembly assembly, Func<Type, bool> interfacePredicate, Func<Type, bool> implementationPredicate)
{
    var interfaces = assembly.ExportedTypes
        .Where(x => x.IsInterface && interfacePredicate(x))
        .ToList();
    var implementations = assembly.ExportedTypes
        .Where(x => !x.IsInterface && !x.IsAbstract && implementationPredicate(x))
        .ToList();
    foreach (var @interface in interfaces)
    {
        var implementation = implementations.FirstOrDefault(x => @interface.IsAssignableFrom(x));
        if (implementation == null) continue;
        services.AddSingleton(@interface, implementation);
    }
    return services;
}

public static IServiceCollection AddSingletonsByConvention(this IServiceCollection services, Assembly assembly, Func<Type, bool> predicate)
    => services.AddSingletonsByConvention(assembly, predicate, predicate);
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过以下简单代码注册所有服务:

var assembly = typeof(MyType).Assembly;
services.AddSingletonsByConvention(assembly, x => x.Name.EndsWith("Service"));
Run Code Online (Sandbox Code Playgroud)

可以随意自定义这些扩展以适应您的需求。例如,如果找不到某些服务的实现,则可以引发异常,如果这样会使您感到更安全。


Tse*_*eng 6

开箱即用的 DI 不支持它,也不打算这样做。内置的 IoC 容器在设计上保持简单,以允许适用于大多数情况的基本依赖项注入。

如果您想要高级功能,例如按约定注册、程序集扫描或装饰器支持,则必须使用第 3 方 IoC 容器,例如 Autofac、SimpleInjector、Castle Windsor。