【问题标题】:Is there a difference between method injection or constructor injection of services in the Configure() method of the Startup class?Startup 类的 Configure() 方法中服务的方法注入和构造函数注入有区别吗?
【发布时间】:2021-02-17 23:22:32
【问题描述】:

根据the docs我们可以在启动类中注入如下服务:

  • IWebHostEnvironment
  • IHostEnvironment
  • IConfiguration

但是我们也可以在Configure()方法中使用方法注入来解析这些服务:

可以在 Configure 方法签名中指定其他服务,例如 IWebHostEnvironment、ILoggerFactory 或 ConfigureServices 中定义的任何内容。如果这些服务可用,就会注入这些服务。

我使用哪种注入变体有区别吗?

具体来说,在构造函数中解析IWebHostEnvironment,然后通过私有字段在Configure()方法中访问它与将其作为方法参数注入有区别吗?

public class Startup
{
    private readonly IWebHostEnvironment env;

    public Startup(IWebHostEnvironment env)
    {
        this.env = env;
    }

    public void Configure(IApplicationBuilder app)
    {
        if (this.env.IsDevelopment())
        [...]
    }
}

对比

public class Startup
{
    public Startup() {}

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        [...]
    }
}

【问题讨论】:

  • 我认为基本上如果您需要以多种方法使用服务,那么将其注入构造函数中是有意义的。否则,注入方法中。

标签: c# asp.net-core .net-core startup


【解决方案1】:

一般来说,构造函数和方法 DI 可以是基于某些框架的偏好或要求,该框架使用这个而不是另一个。在asp.net core(以及一般.net core)中,建议使用构造函数注入,因为它清楚地说明了依赖关系。这比方法注入更有意义。但是在某些情况下,您必须使用方法注入,因为依赖项只能在调用方法时可用,或者至少在构造类时不可用/服务。有时注入的服务仅用于特定的方法调用,在这种情况下将使用方法注入。在某些情况下,服务实例是单例的,但它的方法调用需要一些作用域服务,因此将使用方法注入。该场景的一个示例是使用convention-based middleware 时。基于约定的中间件是单例的,在应用启动时创建一次,而不是为每个请求创建。所以所有作用域服务都必须注入InvokeInvokeAsync 方法。但是,基于工厂的中间件可以将其作用域服务注入构造函数,因为它们可以根据请求创建(注册为作用域或瞬态)。

就像Startup 类的情况一样。您可以将一些内置服务注入Startups 构造函数,例如IConfigurationIWebHostEnvironment、... 通常许多在ConfigureServices 之前可用(之前注册)的服务都可以注入Startup 的构造函数中.这意味着在ConfigureServices 中注册的所有服务都不可用 注入到Startup 的构造函数中。但是,您可以将所有已注册的服务(包括内置服务和您的服务)注入方法 Configure。请注意,注入Configure 的服务应该是单例和瞬态的,对于作用域服务,使用它们时可能会出现问题。这实际上取决于您使用的特定服务。

这是一个示例,显示无法将您自己的服务(在ConfigureServices 中注册)注入Startup 的构造函数:

 public interface ISomeService {}
 public class SomeService : ISomeService {}


 public class Startup {
      //will not work because at this time, the ISomeService has not been registered yet
      public Startup(ISomeService someService){
          //an error will be thrown complaining about not being able to 
          //resolve the ISomeService
      }

      public void ConfigureServices(IServiceCollection services){
          //...
          services.AddSingleton<ISomeService,SomeService>();
          //...
      }
      //this works because at this time the ConfigureServices was called
      //the services container has been built with your registered ISomeService
      public void Configure(IApplicationBuilder app, ISomeService someService){
          //...
      }
 }

【讨论】:

  • 谢谢!因此,对于IWebHostEnvironment,这意味着它没有任何区别,因为它是一个单例,因此在任一变体中都解析为相同的实例。
  • @Sandro 是的,没有区别。
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
相关资源
最近更新 更多