无法在 .NET Core 2.0 的启动构造函数中注入我自己的对象

Cannot inject my own objects in Startup constructor in .NET Core 2.0

我正在尝试使用依赖项注入来注入我自己的 类,如下所示:

// Startup.cs
public class Startup
{
    private readonly ILogger _log;
    private readonly IMainController _controller;
    public Startup(ILoggerFactory loggerFactory, IMainController controller)
    {
        _log = loggerFactory.CreateLogger("Logger");
        _controller = controller;
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMainController, MainController>();
        // services.AddTransient<MainController, MainController>();
    }

然后是要注入的对象MainController

// MainController.cs
public interface IMainController
{
    Task Run(HttpContext context);
}
public class MainController : IMainController
{
    private readonly ILogger _log;

    public MainController(ILoggerFactory loggerFactory)
    {
        _log = loggerFactory.CreateLogger("Logger");
    }

在运行时,我收到以下错误:

Unhandled Exception: System.InvalidOperationException: Unable to resolve service for type 'mtss.ws.IMainController' while attempting to activate 'mtss.ws.Startup'. at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)

我想在 MainController 中注入一个 ILoggerFactory(就像在 Startup 中所做的那样),然后在 Startup 中注入一个新创建的 MainController...

你的设置是不可能的。 Startup 的构造函数将 运行 在你的 ConfigureServices 方法之前,这意味着你试图在你注册它之前注入 IMainController 依赖注入。

我假设你正在构建一个 ASP.Net Core2.0 MVC 应用程序(但是你的 MainController 没有继承自 Controller 所以我对此持怀疑态度)你不需要在 DI 容器中注册你的控制器.您拥有的构造函数应该足以让 ASP.Net 为您注入 ILogger 具体实例。

public MainController(ILoggerFactory loggerFactory)

如果您还想将自己的服务添加到控制器中,控制器构造函数将更改为:-

控制器

public MainController(ILoggerFactory loggerFactory, IMyService myService)

您在 Startup.cs 中的服务注册可能如下所示:-

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddScoped<IMyService, MyService>();
}

我的服务

public interface IMyService
{
    void DoSomethingPLEASE();
}
public class MyService : IMyService
{
    public void DoSomethingPLEASE()
    {
        // Do Something PLEASE, ANYTHING!
    }
}

家庭控制器

public class HomeController : Controller
{
    public HomeController(ILoggerFactory loggerFactory, IMyService myServce)
    {
        myServce.DoSomethingPLEASE();
    }
    public IActionResult Index()
    {
        return View();
    }
}

根据文档,您应该注意以下几点

Services Available in Startup

ASP.NET Core dependency injection provides services during an application's startup. You can request these services by including the appropriate interface as a parameter on your Startup class's constructor or its Configure method. The ConfigureServices method only takes an IServiceCollection parameter (but any registered service can be retrieved from this collection, so additional parameters are not necessary).

Below are some of the services typically requested by Startup methods:

  • In the constructor: IHostingEnvironment, ILogger<Startup>
  • In the ConfigureServices method: IServiceCollection
  • In the Configure method: IApplicationBuilder, IHostingEnvironment, ILoggerFactory

Any services added by the WebHostBuilder ConfigureServices method may be requested by the Startup class constructor or its Configure method. Use WebHostBuilder to provide any services you need during Startup methods.

您正在尝试解析调用 Startup 的构造函数时不可用的服务。 IMainController 在调用构造函数时尚未注册。但是,它应该在 Configure 被调用时可用,允许注入您的自定义服务,因为它是在 ConfigureServices 之后调用的,并且从 RTM 开始,将为 Configure方法。

// Startup.cs
public class Startup {
    private ILogger _log;
    private IMainController _controller;

    public Startup() {

    }

    public void ConfigureServices(IServiceCollection services) {
        services.AddScoped<IMainController, MainController>();
        // services.AddTransient<MainController, MainController>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
               ILoggerFactory loggerFactory, IMainController controller) {
        _log = loggerFactory.CreateLogger("Logger");
        _controller = controller;
        //...other code removed for brevity
    }
}

以上应该适用于 .net-core 2.0

除了@nkosi 在 的回答,您还可以使用 WebHostBuilder ConfigureServices 方法添加依赖项,如文档中所述:

Any services added by the WebHostBuilder ConfigureServices method may be requested by the Startup class constructor or its Configure method. Use WebHostBuilder to provide any services you need during Startup methods.

会是这样的

// ...other code removed for brevity
// in Program.cs
public static void Main(string[] args)
{
    BuildWebHost(args).Run();
}

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
            services.AddScoped<IMainController, MainController>()
        )
        .UseStartup<Startup>()
        .Build();

然后在 Startup.cs 我可以执行以下操作

private readonly ILogger _log;
private readonly IMainController _controller;

public Startup(ILoggerFactory loggerFactory, IMainController controller)
{
    _log = loggerFactory.CreateLogger("Logger");
    _controller = controller;
}

这个 gist 帮助我弄明白了,它有很多有用的例子