【问题标题】:.NET Core dependency injection -> Get all implementations of an interface.NET Core 依赖注入 -> 获取接口的所有实现
【发布时间】:2016-09-19 07:30:32
【问题描述】:

我有一个名为 IRule 的接口和多个实现该接口的类。我想使用.NET Core依赖注入容器来加载IRule的所有实现,所以所有实现的规则。

很遗憾,我无法完成这项工作。我知道我可以将IEnumerable<IRule> 注入控制器的ctor,但我不知道如何在 Startup.cs 中注册此设置

【问题讨论】:

    标签: .net dependency-injection asp.net-core


    【解决方案1】:

    只需一个一个注册所有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&lt;T&gt;

    【讨论】:

    • 解决 IEnumerable 是否存在性能问题?像其中的一打一样,与注入一个抽象工厂然后按名称解析单个服务相比。谢谢
    • @whoever:这是一个无法回答的问题。您必须自己衡量这一点,以确定性能特征在您的特定环境中是否合适。测量,测量,测量。
    • @Steven 谢谢。我只是又看了一眼。的确,即使是我的两个案例也不同。一方面,我循环并调用所有实现,因此注入 IEnumerable 非常有意义;另一方面,每个调用者只需要一个特定的实现,但只有两个,初始化成本可以忽略不计,有点洗。所以我决定将抽象保存到另一天^_^
    • @steven 您将如何订购规则?假设我有规则 1、规则 2 和规则 3。如果您希望顺序为 rule3、rule1、rule2。也许在另一部分中,您希望 rule2 后跟 rule1。我想的一种方法是有一个逗号分隔的列表,它们循环数组并匹配规则名称,但它看起来很hacky。有什么建议吗?
    • 请注意,这也适用于 AddSingleton。
    【解决方案2】:

    对于其他正在寻找答案的人。您还可以检查您的程序集并注册所有实现特定接口的类:

    // 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&lt;IRule&gt;。此解决方案的优点是您不需要将每条规则都添加到依赖注入中。您可以简单地将IRule 的新实现添加到您的项目中,它将自动注册。

    【讨论】:

    • 感谢这个想法!您可能需要考虑使用IsAssignableFrom 而不是GetInterface
    • 感谢您的提示。那会更好。不幸的是,它不起作用。我猜原因是IsAssignableFrom指的是引用,这里无法解决。因此,必须选择通过名称的解决方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 2018-04-05
    • 2016-05-22
    相关资源
    最近更新 更多