【问题标题】:.NET Core Built In Dependency Injection (DI): How can I not new up Dependencies?.NET Core 内置依赖注入 (DI):如何不新建依赖项?
【发布时间】:2022-01-24 01:28:07
【问题描述】:

我目前正在使用 .NET Core 内置的依赖注入 (DI)。

我的应用程序正在使用规则引擎设计模式。

我的一条规则,有一个依赖,它有一个依赖。所以,我必须继续“更新”依赖项的实例。我觉得好像有更好的方法。

这是我的代码示例。

这可行,但我不喜欢我必须新建 DataService 和存储库。

var rules = new List<IRule>
   {
      new Rule1(),
      new Rule2(new DataService(new Repository(CnnStr))) //This is what I don't like
   };
s.AddTransient<IRulesEngine>(sp => new RulesEngine(rules));

我开始设置这个:

s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService>(sp => sp.GetRequiredService<DataService>());

这似乎让我更接近我想要的。但是,我不知道如何用规则实例列表填充规则列表,而不必新建依赖项(DataService 和 Repo)。

类似这样,但我知道这段代码不对。

var rules = new List<IRule>
   {
      s.AddTransient<IRule>(sp => sp.GetRequiredService<Rule1>())
      s.AddTransient<IRule>(sp => sp.GetRequiredService<Rule2>())
   };
s.AddTransient<IRulesEngine>(sp => new RulesEngine(rules));

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • s.AddTransient&lt;IRule, Rule&gt;(); s.AddTransient&lt;IRulesEngine,RulesEngine&gt;(); 应该只要RulesEngine 接受IEnumerable&lt;IRule&gt; 就可以工作。不知道你为什么要把一切都搞得过于复杂。
  • @JeremyLakeman 感谢您的回复,但我认为您并不完全了解情况(或者我误解了您的建议)。我做不到:s.AddTransient();或者至少我认为我做不到,因为我有 2 条规则(实际上我将有大约 20 条规则)。所有规则都实现了 IRule,但都有不同的功能。您熟悉规则引擎设计模式吗?
  • @DanielA.White 谢谢,我会在早上查看这个链接。
  • 并且默认的 DI 容器将 IEnumerable&lt;&gt; 注册为一个开放的泛型。任何具有可枚举构造函数参数的服务都将接收所有已注册的服务。

标签: c# .net .net-core dependency-injection


【解决方案1】:

注册依赖,规则需要

s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService, DataService>(); // you don't need sp here

然后注册规则。 TryAddEnumerable 确保不会有相同接口的重复实现

s.TryAddEnumerable(new[] {
  ServiceDescriptor.Transient<IRule, Rule1>();
  ServiceDescriptor.Transient<IRule, Rule2>();
});

注册规则引擎

s.AddTransient<IRulesEngine, RulesEngine>();

注意规则引擎应该依赖于IEnumerable&lt;IRule&gt;

【讨论】:

  • 谢谢。我会在早上尝试这第一件事。
【解决方案2】:

我今天早上开始工作了。

我从很多回复中使用了一点。但是,@Daniel A. White 建议的下面的链接对我来说是所有这些。

.NET Core dependency injection -> Get all implementations of an interface

也许我像@Jeremey Lakeman 建议的那样过于复杂。

这是我在 Program.cs 文件中所做的更改:

s.AddTransient<IRepository>(sp => new Repository(CnnStr));
s.AddTransient<IDataService, DataService>();

s.AddTransient<IRule, Rule1>();
s.AddTransient<IRule, Rule2>();

s.AddTransient<IRulesEngine, RulesEngine>();

加上我对规则引擎所做的更改:

private readonly IEnumerable<IRule> _rules;

public RulesEngine(IEnumerable<IRule> rules)
   {
      _rules = rules;
   }

public void RunRules()
   {   
      foreach (var rule in _rules)
      {
         rule.Execute(canonical);
      }            
   }

【讨论】:

    猜你喜欢
    • 2020-12-20
    • 2016-05-22
    • 1970-01-01
    • 2018-03-03
    • 2021-10-23
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多