【发布时间】:2016-09-19 07:30:32
【问题描述】:
我有一个名为 IRule 的接口和多个实现该接口的类。我想使用.NET Core依赖注入容器来加载IRule的所有实现,所以所有实现的规则。
很遗憾,我无法完成这项工作。我知道我可以将IEnumerable<IRule> 注入控制器的ctor,但我不知道如何在 Startup.cs 中注册此设置
【问题讨论】:
标签: .net dependency-injection asp.net-core
我有一个名为 IRule 的接口和多个实现该接口的类。我想使用.NET Core依赖注入容器来加载IRule的所有实现,所以所有实现的规则。
很遗憾,我无法完成这项工作。我知道我可以将IEnumerable<IRule> 注入控制器的ctor,但我不知道如何在 Startup.cs 中注册此设置
【问题讨论】:
标签: .net dependency-injection asp.net-core
只需一个一个注册所有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。
IsAssignableFrom指的是引用,这里无法解决。因此,必须选择通过名称的解决方法。