[英]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.