繁体   English   中英

构造函数中的ASP.NET Core选项依赖项

[英]ASP.NET Core option dependency in constructor

我正在使用ASP.NET Core,并且尝试创建一个具有可选参数的可解析类:

public class Foo
{
     public Foo() : this(null)
     {}

     public Foo(IValidator<FooEntity> validator)
     {
     }
}

我为该对象创建了两个构造函数,因此,如果未找到依赖项,我将假定它会退回到默认构造函数。

但是,当我运行我的应用程序时,会出现此错误

附加信息:尝试激活“ Foo”时,无法解析类型为“ FluentValidation.IValidator`1 [FooEntity]”的服务

我知道可能有一种方法可以手动解决Foo对象的构造。 但是我不希望这样做,因为我必须为我创建的没有验证器的每个类都这样做。

没有人知道如何将ASP.NET Core DI配置为在找不到依赖项时回退到其他构造函数吗?

编辑

抱歉,我之前应该更清楚一点。

我实际上是在CRUD服务的基类中引用这个Foo类,该类将反复使用。

我正在寻找一种通用解决方案,该解决方案不需要我配置每次创建的每个服务。

因此,使用lambda来解决此问题不是一种选择,空对象模式似乎是可行的,但我无法理解如何编写通用的模式,而不必为每个服务进行配置

我认为容器的一般行为是使用最多的参数来解析构造函数。

基本上, AddTransient作用如下:

services.AddTransient<Foo>();
//equals to:
services.AddTransient<Foo>(c=> new Foo(c.GetService<IValidator<FooEntity>()));

因此,您可以这样自己注册:

services.AddTransient<Foo>(c=> new Foo());

此时,在启动类中,您应该知道IValidator<FooEntity>是否已注册。 或者,如果您使用反射,则将此逻辑添加到反射代码中。

区别

这两个选项之间的区别在于,第一个选项是在启动时创建用于解析类的lambda function +如果更改构造函数,则无需在其他地方更改代码。

如果您自己创建lambda,则该lambda是在构建时编译的,因此从理论上讲,启动速度应该更快(我尚未对此进行测试)。

伟大的心态

最好的心态是拥有您正在使用的库。 在Visual Studio / Resharper中,您可以反编译源代码,或者现在可以在github上找到存储库。

在这里,您可以看到源代码,可以看到如何将services参数“编译”到IServiceProvider(请参阅BuildServiceProvider()方法,它将为您提供很多见识。)

还要看:

做到这一点的最好方法是,(抱歉伪代码,但我手边没有编辑器)。

getTypes()
    .Where(x=> x.EndsWith("Entity") //lets get some types by logic
    .Select(x=> typeof(IValidator<>).MakeGeneric(x)) //turn IValidator into IValidator<T>
    .Where(x=> !services.IsRegistered(x))
    .Each(x=> services.Add(x, c=> null)) //register value null for IValidator<T> 

您需要先注册 IValidator<T>

  var services = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
  services.AddTransient<IValidator<FooEntity>, RealValidator<FooEntity>>();
  services.AddTransient<Foo>();

  var serviceProvider = services.BuildServiceProvider();
  var validator = serviceProvider.GetService<IValidator<FooEntity>>();
  var foo = serviceProvider.GetService<Foo>();

  Assert.NotNull(validator);
  Assert.NotNull(foo);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM