将 Microsoft.Extensions.DependencyInjection 集成到 ASP.NET 4.6.1 项目中
Integrating Microsoft.Extensions.DependencyInjection in ASP.NET 4.6.1 project
我的大部分项目都使用 .NET Core 3.1,但目前已有一个项目使用 .NET Framework 4.6.1
我在对 .NET Framework 4.6.1 实施依赖项注入时遇到困难,不确定我哪里做错了。
这是我到目前为止的理解和所做的:
- .NET Framework 4.6.1 运行s Global.asax.cs -> Application_Start() 在 运行
- .NET Core 3.1 运行s Startup.cs 基于 运行
这就是在 .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>();
}
如何使用 .NET Framework 4.6.1 中的 MemberService 添加 IMemberServices 的依赖关系
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//What to write here?
}
}
ASP.NET MVC 实现
WARNING: This answer will not work when building a Web API web site. For Web API, please see my other answer.
假设您正在构建一个 ASP.NET MVC 应用程序,您将必须实现自定义 System.Web.Mvc.IControllerFactory
并替换 [=13] 中的默认=] 事件。这是一个完整的工作示例,展示了如何将 Microsoft.Extensions.DependencyInjection (MS.DI) 集成到 ASP.NET MVC 4.6.1 及更高版本中:
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();
}
}
虽然也可以实现自定义 IDependencyResolver
而不是 IControllerFactory
,但使用控制器工厂更简单,因为您有一个清晰的位置来开始新的 IServiceScope
。创建服务范围并从该范围解析控制器很重要,因为直接从根解析控制器 IServiceProvider
会导致内存泄漏和多线程问题。
ASP.NET Web API 实现
WARNING: This answer will not work when building an MVC web site. For MVC, please see my other answer.
假设您正在构建一个 ASP.NET Web API 应用程序,您将必须实现自定义 System.Web.Http.Dispatcher.IHttpControllerActivator
并替换默认的在你的 Application_Start
活动中。这是一个完整的工作示例,展示了如何将 Microsoft.Extensions.DependencyInjection (MS.DI) 集成到 ASP.NET Web API 4.6.1 及更高版本中:
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);
}
}
虽然也可以实现自定义 IDependencyResolver
而不是 IHttpControllerActivator
,但使用控制器激活器更简单,因为您有一个清晰的位置来开始新的 IServiceScope
。创建服务范围并从该范围解析控制器很重要,因为直接从根解析控制器 IServiceProvider
会导致内存泄漏和多线程问题。
我的大部分项目都使用 .NET Core 3.1,但目前已有一个项目使用 .NET Framework 4.6.1
我在对 .NET Framework 4.6.1 实施依赖项注入时遇到困难,不确定我哪里做错了。
这是我到目前为止的理解和所做的:
- .NET Framework 4.6.1 运行s Global.asax.cs -> Application_Start() 在 运行
- .NET Core 3.1 运行s Startup.cs 基于 运行
这就是在 .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>();
}
如何使用 .NET Framework 4.6.1 中的 MemberService 添加 IMemberServices 的依赖关系
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//What to write here?
}
}
ASP.NET MVC 实现
WARNING: This answer will not work when building a Web API web site. For Web API, please see my other answer.
假设您正在构建一个 ASP.NET MVC 应用程序,您将必须实现自定义 System.Web.Mvc.IControllerFactory
并替换 [=13] 中的默认=] 事件。这是一个完整的工作示例,展示了如何将 Microsoft.Extensions.DependencyInjection (MS.DI) 集成到 ASP.NET MVC 4.6.1 及更高版本中:
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();
}
}
虽然也可以实现自定义 IDependencyResolver
而不是 IControllerFactory
,但使用控制器工厂更简单,因为您有一个清晰的位置来开始新的 IServiceScope
。创建服务范围并从该范围解析控制器很重要,因为直接从根解析控制器 IServiceProvider
会导致内存泄漏和多线程问题。
ASP.NET Web API 实现
WARNING: This answer will not work when building an MVC web site. For MVC, please see my other answer.
假设您正在构建一个 ASP.NET Web API 应用程序,您将必须实现自定义 System.Web.Http.Dispatcher.IHttpControllerActivator
并替换默认的在你的 Application_Start
活动中。这是一个完整的工作示例,展示了如何将 Microsoft.Extensions.DependencyInjection (MS.DI) 集成到 ASP.NET Web API 4.6.1 及更高版本中:
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);
}
}
虽然也可以实现自定义 IDependencyResolver
而不是 IHttpControllerActivator
,但使用控制器激活器更简单,因为您有一个清晰的位置来开始新的 IServiceScope
。创建服务范围并从该范围解析控制器很重要,因为直接从根解析控制器 IServiceProvider
会导致内存泄漏和多线程问题。