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?
}
}
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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.