![](/img/trans.png)
[英]Determining which implementation to inject at runtime using .NET Core dependency injection
[英]Use the ActivatorUtilities to determine which implementation to inject at runtime
我正在使用內置的 .Net Core IoC 容器來解決應用程序的依賴關系。 我配置它的方式如下,使用 Scrutor 掃描我的程序集:
services.Scan(s => s
.FromAssembliesOf(currentAssemblyTypesList)
.AddClasses(false)
.UsingRegistrationStrategy(RegistrationStrategy.Append)
.AsImplementedInterfaces()
.WithTransientLifetime());
到目前為止,我已經有了一些簡單的情況,其中每個接口都由一個依賴項實現,因此以前的配置可以完美地解決整個依賴項樹。
現在考慮以下代碼:
public interface IService {}
public class ServiceOne : IService
{
public ServiceOne(IDependency dependency) {}
}
public class ServiceTwo : IService
{
public ServiceTwo(IDependency dependency) {}
}
public class SomeClass
{
public SomeClass(IService service) {}
public void DoSomething()
{
this.service.SomeMethod();
}
}
在這種情況下,“SomeClass”位於依賴樹的中間,我有兩個實現相同接口的服務,並且直到運行時才知道應該將哪個服務注入到“SomeClass”中。 出於不重要的原因,我被要求為此使用 ActivatorUtilities 類。
我正在處理兩種確定應該實例化哪個 IService 的場景:
所以問題是我需要在依賴項注冊過程中更改或添加什么,以及如何使用 ActivatorUtilities 類來實現這些目標?
謝謝你。
不太清楚您要實現的目標,但我認為它是這樣的?
services.AddTransient<IService>(sp =>
{
if (condition1 && condition2)
ActivatorUtilities.CreateInstance<ServiceOne>(sp);
else
ActivatorUtilities.CreateInstance<ServiceTwo>(sp);
});
因此,最棘手的部分是當注冊已經發生並且事實證明有一種方法可以替換特定定義時,弄清楚如何處理第一種情況。 這可以通過以下代碼完成:
Func<IServiceProvider, object> factoryMethod = sp =>
{
if (condition1 && condition2)
{
return ActivatorUtilities.CreateInstance<ServiceOne>(sp);
}
else
{
return ActivatorUtilities.CreateInstance<ServiceTwo>(sp);
}
};
services.Replace(ServiceDescriptor.Describe(typeof(IService), factoryMethod, ServiceLifetime.Transient));
當在依賴關系注冊時知道條件 1和條件 2時,這非常有效,換句話說,在發出任何請求之前的應用程序啟動時。
對於在應用程序運行並發出請求之前不知道條件的其他場景,因為內置的 .Net Core IoC 容器不像 Castle 或 Autofac 等其他容器那樣功能豐富,一種方法是手動創建一個工廠方法對象,如下所示:
public interface IServiceFactory
{
IService Get(MyObject myObject);
}
public class ServiceFactory : IServiceFactory
{
private readonly IServiceProvider sp;
public ServiceFactory(IServiceProvider sp)
{
this.sp = sp;
}
public IService Get(MyObject myObject)
{
if(myObject.SomeProperty == "whatever")
{
return ActivatorUtilities.CreateInstance<ServiceOne>(this.sp);
}
else
{
return ActivatorUtilities.CreateInstance<ServiceTwo>(this.sp);
}
}
}
這里唯一要記住的是,可以而且應該在定義所有其余應用程序接口的任何地方定義接口,並且您不希望應用程序的其余部分與MicrosoftExtensions.DependencyInjection包緊密耦合,因為IServiceProvider接口的使用,因此工廠的實現應該在定義注冊邏輯的其余部分的任何地方。
我真的很難找到一個ActivatorUtilities.CreateFactory方法的例子,它會給我這樣的東西,但找不到一個。 我希望這對某人有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.