I'm trying to inject my own classes using dependency injection, like this:
// 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>();
}
and then MainController, the object to be injected
// 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");
}
At runtime, I get the following error:
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)
I want to inject an ILoggerFactory in MainController (as it's doing in Startup) and then inject a newly created MainController in Startup...
Besides @nkosi answer at https://stackoverflow.com/a/46013224/47633, you can also add dependencies using the WebHostBuilder ConfigureServices method, like stated in the docs:
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.
It would be something like this
// ...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();
and then in Startup.cs I can do the following
private readonly ILogger _log;
private readonly IMainController _controller;
public Startup(ILoggerFactory loggerFactory, IMainController controller)
{
_log = loggerFactory.CreateLogger("Logger");
_controller = controller;
}
This gist helped me figure it out, it's got lot's of useful examples
According to documentation, you should note the following
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 anIServiceCollection
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 theStartup
class constructor or itsConfigure
method. UseWebHostBuilder
to provide any services you need duringStartup
methods.
You are trying to resolve a service that is not available when the constructor of Startup
is called. IMainController
is not registered as yet when the constructor is called. however, It should be available by the time Configure
is called, allowing an opportunity to inject your custom service because it is called after ConfigureServices
and as of RTM, a scoped service provider will be created for the Configure
method.
// 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
}
}
The above should work in .net-core 2.0
Your setup is impossible. The constructor of Startup
will run before your ConfigureServices
method, which means you are trying to inject IMainController
before you register it for dependency injection.
I will assume you are building an ASP.Net Core2.0 MVC Application (but your MainController does not inherit from Controller so I am suspicious about this) You do not need to register your controller in the DI container. The Constructor you have should be sufficient for ASP.Net to inject the ILogger concrete instance for you.
public MainController(ILoggerFactory loggerFactory)
If you wanted to also add your own service into the controller, the controllers constructor would change to be thus:-
Controller
public MainController(ILoggerFactory loggerFactory, IMyService myService)
Your service registration in Startup.cs may look like this:-
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<IMyService, MyService>();
}
MyService
public interface IMyService
{
void DoSomethingPLEASE();
}
public class MyService : IMyService
{
public void DoSomethingPLEASE()
{
// Do Something PLEASE, ANYTHING!
}
}
HomeController
public class HomeController : Controller
{
public HomeController(ILoggerFactory loggerFactory, IMyService myServce)
{
myServce.DoSomethingPLEASE();
}
public IActionResult Index()
{
return View();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With