我有一个名为IRule
的接口,以及多个实现该接口的类。我想使用.NET Core依赖注入容器来加载所有实现了IRule
的规则。
可惜我无法实现这个目标。我知道可以将IEnumerable<IRule>
注入到我的控制器构造函数中,但我不知道如何在Startup.cs中注册这个设置。
我有一个名为IRule
的接口,以及多个实现该接口的类。我想使用.NET Core依赖注入容器来加载所有实现了IRule
的规则。
可惜我无法实现这个目标。我知道可以将IEnumerable<IRule>
注入到我的控制器构造函数中,但我不知道如何在Startup.cs中注册这个设置。
只需要逐个注册所有的IRule
实现,Microsoft.Extensions.DependencyInjection (MS.DI)库会将其解析为一个IEnumerable<T>
。例如:
这只是简单地将所有IRule
的实现都注册一遍;Microsoft.Extensions.DependencyInjection (MS.DI)库可以将其解析为一个IEnumerable<T>
。
services.AddTransient<IRule, Rule1>();
services.AddTransient<IRule, Rule2>();
services.AddTransient<IRule, Rule3>();
services.AddTransient<IRule, Rule4>();
消费者:
public sealed class Consumer
{
private readonly IEnumerable<IRule> rules;
public Consumer(IEnumerable<IRule> rules)
{
this.rules = rules;
}
}
注意:MS.DI支持的唯一集合类型是IEnumerable<T>
。
对于其他寻找答案的人。您还可以通过查看汇编并注册实现特定接口的所有类:
// Get all implementations of IRule and add them to the DI
var rules = typeof(Program).Assembly.GetTypes()
.Where(x => !x.IsAbstract && x.IsClass && x.GetInterface(nameof(IRule)) == typeof(IRule));
foreach (var rule in rules)
{
services.Add(new ServiceDescriptor(typeof(IRule), rule, ServiceLifetime.Transient));
// Replace Transient with whatever lifetime you need
}
这也会为您的依赖注入提供一个 IEnumerable<IRule>
。这种解决方案的优点是,您不需要将每个规则都添加到您的依赖注入中。您只需向项目中添加 IRule
的新实现,它就会自动注册。
IsAssignableFrom
而不是GetInterface
。 - Vincent BitterIsAssignableFrom
指的是引用,这里无法解析。因此,必须选择通过名称的解决方法。 - Sebastian.Where(x => typeof(IRule).IsAssignableFrom(x));
- DennischSebastian和Dennisch的答案合并:
var rules = Assembly.GetExecutingAssembly().GetTypes()
.Where(x => !x.IsAbstract && x.IsClass && typeof(IRule).IsAssignableFrom(x));
foreach (var rule in rules)
{
services.Add(new ServiceDescriptor(typeof(IRule), rule, ServiceLifetime.Transient));
}