【问题标题】:Resolving dependency by parameter - without pre instantiating services?通过参数解决依赖关系 - 没有预先实例化服务?
【发布时间】:2019-07-20 20:21:43
【问题描述】:

简化,我有这个简单的代码:

    services.AddScoped<IFruit>(provider =>
        {
            var httpContext = provider.GetRequiredService<IHttpContextAccessor>().HttpContext;

            if (httpContext.Request.QueryString.HasValue)
            {
                return new AppleService(...);
            }
            else return new OrangeService(...);
        });

问题是AppleService & OrangeSservice 在构造函数中有很多(和不同的)参数(其他 DI 参数),我想我在这里走错了方向。

public class AppleService:IFruit
{
 public  AppleService (a,b,c,d,e....){}
}

public class OrangeService:IFruit
{
 public  OrnageService (o,i,u,y,....){}
}

另外,我不想预先实例化这两个服务来决定去哪一个。

我希望实例化仅用于我将要使用的服务。 (根据请求参数)

但是,我在下面的answer 中看到了一个不错的解决方案(使用工厂),但是正如您所见,即使他只需要一个服务,他也会注入并实例化这两个服务。

(在我的场景中,我需要 Scoped 实例化)

问题:

如何根据请求参数实例化我需要的服务?

【问题讨论】:

  • 我可以想出几种方法来实现这一点,但你的基本方法可能是一个错误。

标签: c# asp.net-core


【解决方案1】:

如果将服务注册到 DI 容器中,然后使用ServiceProvider 解决它们,则可以通过大量参数解决问题。

这样您就不需要手动实例化服务。

services.AddScoped<AppleService>();
services.AddScoped<OrangeService>();
services.AddScoped<IFruit>(provider =>
{
    var httpContext = provider.GetRequiredService<IHttpContextAccessor>().HttpContext;

    if (httpContext.Request.QueryString.HasValue)
    {
        return provider.GetRequiredService<AppleService>();
    }

    return provider.GetRequiredService<OrangeService>();
});

【讨论】:

  • 作用域服务似乎在其作用域中表现得像单例。在需要它们之前它们不会被实例化,但在那之后它们总是相同的实例。我刚刚用基本的 ValuesController 尝试了这个,在 GET 上我需要一个 OrangeService,在 post 上,一个 AppleService。我在两个服务构造函数中都放了一个记录器,结果是这样的:imgur.com/a/IolMYiq
  • 所以 services.AddScoped&lt;OrangeService&gt;(); 不会实例化它,而 provider.GetRequiredService&lt;AppleService&gt;() 会实例化它们?
  • 是的。实例化不是在您将类添加到 ServiceCollection 时发生,而是在您使用 ServiceProvider 获取类的实例时发生。看起来很合理,我的意思是,如果您的 DI 容器中有 30 个类,则无需根据请求实例化每个类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多