首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ActivatorUtilities确定要在运行时注入哪个实现

使用ActivatorUtilities确定要在运行时注入哪个实现
EN

Stack Overflow用户
提问于 2019-12-12 21:38:29
回答 2查看 1.9K关注 0票数 0

我正在使用内置的.Net核心IoC容器来解决应用程序的依赖关系。我配置它的方式如下,使用Scrutor扫描我的程序集:

代码语言:javascript
复制
services.Scan(s => s
    .FromAssembliesOf(currentAssemblyTypesList)
    .AddClasses(false)
    .UsingRegistrationStrategy(RegistrationStrategy.Append)
    .AsImplementedInterfaces()
    .WithTransientLifetime());

到目前为止,我有一些简单的例子,其中每个接口都是由一个依赖项实现的,所以以前的配置可以很好地解决整个依赖树。

现在考虑以下代码:

代码语言:javascript
复制
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. 在应用程序启动时设置了一个标志,用于确定在注册之前要使用的服务(对于类似的设置,但不是对于相同的依赖树)。在执行"DoSomething“方法期间,
  2. 将决定应该使用哪一个服务,所以我猜某种工厂应该注册并注入到"SomeClass".

中。

因此,问题是我需要更改或添加到依赖项注册过程中,以及如何使用ActivatorUtilities类来实现这些目标?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-17 15:42:35

所以,最棘手的部分是弄清楚当注册已经进行时,如何处理第一个场景,结果是有一种方法来替换特定的定义。这可以通过以下代码来实现:

代码语言:javascript
复制
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));

condition1condition2在依赖项注册时已知时,换句话说,在发出任何请求之前,在应用程序启动时,这很好地工作。

对于另一种情况,在运行应用程序和发出请求之前不知道条件,因为内置的.Net核心IoC容器不像城堡或Autofac等其他容器那样功能丰富,一种方法是手动创建工厂方法对象,如下所示:

代码语言:javascript
复制
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接口而紧密耦合到IServiceProvider包,因此工厂的实现应该位于定义注册逻辑其余部分的位置。

我非常努力地寻找一个ActivatorUtilities.CreateFactory方法的例子,它会给我这样的东西,但却找不到。我希望这对某人有用。

票数 1
EN

Stack Overflow用户

发布于 2019-12-13 04:57:38

不太清楚你想要达到什么目的,但我认为是这样的吗?

代码语言:javascript
复制
services.AddTransient<IService>(sp =>
{
    if (condition1 && condition2)
        ActivatorUtilities.CreateInstance<ServiceOne>(sp);
    else
        ActivatorUtilities.CreateInstance<ServiceTwo>(sp);
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59313099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档