Reputation: 251
I have been using .NET Core 3.1 for most of my projects, but currently there is an existing project that uses .NET Framework 4.6.1
I am having difficulties to implement dependency injection to the .NET Framework 4.6.1, not sure where did I do wrong.
Here is what I understand and done so far:
This is how the Dependency Injection was added in the .NET Core 3.1
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
RegisterServices(services);
ServiceProvider = services.BuildServiceProvider();
}
private void RegisterServices(IServiceCollection services)
{
services.AddOptions();
services.AddTransient<IMemberServices, MemberService>();
}
How do I add the dependency for IMemberServices with MemberService at .NET Framework 4.6.1
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//What to write here?
}
}
Upvotes: 7
Views: 7679
Reputation: 172646
WARNING: This answer will not work when building a Web API web site. For Web API, please see my other answer.
Assuming you are building an ASP.NET MVC application, you will have to implement a custom System.Web.Mvc.IControllerFactory
and replace the default one inside your Application_Start
event. Here's a complete working example that shows how to integrate Microsoft.Extensions.DependencyInjection (MS.DI) into ASP.NET MVC 4.6.1 and up:
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Microsoft.Extensions.DependencyInjection;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var services = new ServiceCollection();
// Register all your controllers and other services here:
services.AddTransient<HomeController>();
var provider = services.BuildServiceProvider(new ServiceProviderOptions
{
// Prefer to keep validation on at all times
ValidateOnBuild = true,
ValidateScopes = true
});
ControllerBuilder.Current.SetControllerFactory(
new MsDiControllerFactory(provider));
}
}
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Extensions.DependencyInjection;
public class MsDiControllerFactory : DefaultControllerFactory
{
private readonly ServiceProvider provider;
public MsDiControllerFactory(ServiceProvider provider) => this.provider = provider;
protected override IController GetControllerInstance(
RequestContext requestContext, Type controllerType)
{
IServiceScope scope = this.provider.CreateScope();
HttpContext.Current.Items[typeof(IServiceScope)] = scope;
return (IController)scope.ServiceProvider.GetRequiredService(controllerType);
}
public override void ReleaseController(IController controller)
{
base.ReleaseController(controller);
var scope = HttpContext.Current.Items[typeof(IServiceScope)] as IServiceScope;
scope?.Dispose();
}
}
Although it's also possible to implement a custom IDependencyResolver
instead of an IControllerFactory
, using a controller factory is simpler because you have a clear place to start a new IServiceScope
. Creating a service scope and resolving a controller from that scope is important, because resolving your controllers directly from the root IServiceProvider
will lead to memory leaks and multi-threading issues.
Upvotes: 9
Reputation: 172646
WARNING: This answer will not work when building an MVC web site. For MVC, please see my other answer.
Assuming you are building an ASP.NET Web API application, you will have to implement a custom System.Web.Http.Dispatcher.IHttpControllerActivator
and replace the default one inside your Application_Start
event. Here's a complete working example that shows how to integrate Microsoft.Extensions.DependencyInjection (MS.DI) into ASP.NET Web API 4.6.1 and up:
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Microsoft.Extensions.DependencyInjection;
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var services = new ServiceCollection();
// Register all your controllers and other services here:
services.AddTransient<Controllers.ValuesController>();
var provider = services.BuildServiceProvider(new ServiceProviderOptions
{
// Prefer to keep validation on at all times
ValidateOnBuild = true,
ValidateScopes = true
});
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new MsDiHttpControllerActivator(provider));
}
}
using System;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using Microsoft.Extensions.DependencyInjection;
public class MsDiHttpControllerActivator : IHttpControllerActivator
{
private readonly ServiceProvider provider;
public MsDiHttpControllerActivator(ServiceProvider provider)
{
this.provider = provider;
}
public IHttpController Create(
HttpRequestMessage request, HttpControllerDescriptor descriptor, Type type)
{
var scope = this.provider.CreateScope();
request.RegisterForDispose(scope);
return (IHttpController)scope.ServiceProvider.GetRequiredService(type);
}
}
Although it's also possible to implement a custom IDependencyResolver
instead of an IHttpControllerActivator
, using a controller activator is simpler because you have a clear place to start a new IServiceScope
. Creating a service scope and resolving a controller from that scope is important, because resolving your controllers directly from the root IServiceProvider
will lead to memory leaks and multi-threading issues.
Upvotes: 9