【问题标题】:root scope of DI containerDI容器的根范围
【发布时间】:2019-08-27 08:07:30
【问题描述】:

下面是示例代码:

// startup.cs
public void ConfigureServices(IServiceCollection services) 
{
   services.AddScoped<ConcreteA>;
   services.AddScoped<ConcreteB>;
   services.AddScoped<ConcreteBDependency>;

}

public void Configure(IApplicationBuilder app) {
   app.UseStatusCodePages();
   app.UseDeveloperExceptionPage();
   app.UseMvcWithDefaultRoute();
   ConcreteA.Run(app.ApplicationServices);
}
_____________________________________________________

public class ConcreteA
{
   public static Run(IServiceProvider serviceProvider)
   {
      ConcreteB _concreteB = serviceProvider.GetRequiredService<ConcreteB>();
      ... 
   }

}

public class ConcreteB
{
   private ConcreteBDependency _dependency ;
   public ConcreteB(ConcreteBDependency denpendency)
   {
      _dependency = denpendency
   }
}

我问了很多关于服务范围的问题,我认为这个问题将是最后一块拼图:

以下是我的问题:

Q1-_concreteB是在DI容器的根作用域下创建的吗?

Q2-由于ConcreteB 具有ConcreteBDependency 的依赖关系,ConcreteBDependency 的实例(假设它在内部称为_dependency)之前_concreteB 是通过serviceProvider.GetRequiredService&lt;ConcreteB&gt;(); 创建的,@987654329 也是如此@也在DI容器的根作用域下创建?

Q3-如果_concreteB_dependency都创建在DI容器的根作用域下,我们是否需要禁用program.cs中的作用域验证检查为

public static IWebHost BuildWebHost(string[] args) =>
 WebHost.CreateDefaultBuilder(args)
 .UseStartup<Startup>()
 .UseDefaultServiceProvider(options =>
 options.ValidateScopes = false)
 .Build();

【问题讨论】:

  • serviceProvider in ConcreteA.Run 是与app.ApplicationServices 相同的对象,因此您只是针对同一个服务提供者实例调用.GetRequiredService,尽管在不同的位置。对于 .NET,调用方法时没有区别。
  • @John 和 _concreteB_dependency 都是在 DI 容器的根范围下创建的,
  • 不清楚你在说什么。什么是“根范围”?有一种基本上“没有范围”的情况,这将是最接近“根”的东西,但这只是具有单例生命周期的对象。所有其他对象都在 some 范围内创建。
  • 对于具有“范围”生命周期的服务,这通常等同于 ASP.NET Core 中的请求,即它们存在于接收请求和最终响应该请求之间发送。在此期间,在单个请求的上下文中,无论注入多少次,实例都是相同的。

标签: c# dependency-injection asp.net-core-mvc


【解决方案1】:

Q1- _concreteB 是在 DI 容器的根作用域下创建的吗?

是的,IServiceProvider serviceProvider 是根服务提供者。但是,您无法直接从根提供程序解析范围服务。尝试改变

    public class ConcreteA
    {
        public static void Run(IServiceProvider serviceProvider)
        {
            ConcreteB _concreteB = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<ConcreteB>();
        }
    }

Q2-因为 ConcreteB 有一个 ConcreteBDependency 的依赖,一个 ConcreteBDependency 的实例(假设它被称为 _dependency 内部) before_concreteB 是通过 serviceProvider.GetRequiredService();, _dependency 也是 也是在 DI 容器的根作用域下创建的?

对于ConcreteBDependency,它由服务集合中的范围解析。同样,您无法从根范围解析服务。

Q3- 如果 _concreteB 和 _dependency 都在 DI 下创建 容器的根范围,我们是否需要禁用范围验证 签入 program.cs 为

ValidateScopes 的默认值是 true,除非您确切地知道自己在做什么,否则您应该保留它,否则您可能会因未发布的服务而面临严重的内存泄漏(或对象已处理异常)的风险。

您可以参考Scope validation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多