簡體   English   中英

使用 ActivatorUtilities 確定在運行時注入哪個實現

[英]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 的場景:

  1. 在應用程序啟動時,設置一個標志來確定在注冊發生之前要使用哪個服務(對於類似的設置,但不是對於相同的依賴樹)。
  2. 在“DoSomething”方法的執行過程中,會決定應該使用這兩個服務中的哪一個,所以我猜應該注冊某種工廠並將其注入“SomeClass”。

所以問題是我需要在依賴項注冊過程中更改或添加什么,以及如何使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM