ASP.NET CORE 重写IControllerActivator实现默认IOC属性与方法注入
1.创建控制器的过程依赖众多不同的提供者和工厂类,但最终是由实现IControllerActivator接口的实例来决定的。实现类只需要实现两个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public interface IControllerActivator { // // 摘要: // Creates a controller. // // 参数: // context: // The Microsoft.AspNetCore.Mvc.ControllerContext for the executing action. object Create(ControllerContext context); // // 摘要: // Releases a controller. // // 参数: // context: // The Microsoft.AspNetCore.Mvc.ControllerContext for the executing action. // // controller: // The controller to release. void Release(ControllerContext context, object controller); } |
如你所见,该Create方法传递了用于创建控制器的ControllerContext实例。控制器的创建方式取决于具体的实现。
2.在各大第三方IOC容器中,实现方法注入与属性注入都是先要标记特性所以我们第一步,先新建两个特性
代表属性注入的特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using System.Collections.Generic; using System.Text; namespace GreenUnity.Common.Attributes { /// <summary> /// 限制特性只能标记在属性上(该特性什么都不做,只用来标记属性注入) /// </summary> [AttributeUsage(AttributeTargets.Property)] public class PropertyInjectionAttribute:Attribute { } } |
代表方法注入的特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using System.Collections.Generic; using System.Text; namespace GreenUnity.Common.Attributes { /// <summary> /// 限制特性只能标记在方法上(该特性什么都不做,只用来标记方法注入) /// </summary> [AttributeUsage(AttributeTargets.Method)] public class MethodInjectionAttribute:Attribute { } } |
3.前面我们讲过,控制器的实例化是来自于IControllerActivator接口实列的Create方法,我们新建一个类,继承IControllerActivator接口,实现Create方法,在Create方法里做属性注入与方法注入的实现。注意此扩展方法未解决循环依赖问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | using GreenUnity.Common.Attributes; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace GreenUnity.Common.Extend { public class CustomControllerActivator : IControllerActivator { /// <summary> /// 该方法扩展框架IOC属性与方法注入但是未解决循环依赖问题.使用时切勿循环依赖会死循环内存溢出 /// </summary> /// <param name="context"></param> /// <returns></returns> public object Create(ControllerContext context) { //获得框架得服务提供对象,用于实列化控制器 IServiceProvider serviceProvider = context.HttpContext.RequestServices; //获取控制器类型 Type type = context.ActionDescriptor.ControllerTypeInfo.AsType(); //实列化控制器 object Context = serviceProvider.GetService(type); //属性注入 PropertyInjection(type, serviceProvider, Context); //方法注入 MethodInjection(type, serviceProvider, Context); return Context; //把实列化的控制器返回 } /// <summary> /// 属性注入 /// </summary> /// <param name="type"></param> /// <param name="serviceProvider"></param> public void PropertyInjection(Type type, IServiceProvider serviceProvider, object Context) { try { //根据自定义特性确定要属性注入的属性。 //利用反射获取控制器中应用了PropertyInjectionAttribute的属性。 foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.IsDefined( typeof (PropertyInjectionAttribute), true ))) { Type PropertyType = propertyInfo.PropertyType; //获取当前属性的类型。注:GetType()获取的是当前对象的类型 object property = serviceProvider.GetService(PropertyType); //利用框架的服务提供对象 创建对象 PropertyInjection(PropertyType, serviceProvider, property); //如果有多层注入需要递归创建对象,把当前对象传入。 MethodInjection(PropertyType, serviceProvider, property); //如果有多层注入需要递归创建对象,把当前对象传入。 propertyInfo.SetValue(Context, property); //给属性赋值 } } catch (Exception ex) { } } /// <summary> /// 方法注入 /// </summary> /// <param name="type"></param> /// <param name="serviceProvider"></param> /// <param name="Context"></param> public void MethodInjection(Type type, IServiceProvider serviceProvider, object Context) { try { //根据自定义特性确定要方法注入的方法。 //利用反射获取控制器中应用了MethodInjectionAttribute特性的方法。 foreach (MethodInfo memberInfo in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.IsDefined( typeof (MethodInjectionAttribute)))) { ParameterInfo[] parameterInfos = memberInfo.GetParameters(); //获取方法参数列表 object [] Parameters = new object [parameterInfos.Length]; //循环实列化方法参数 for ( int i = 0; i < parameterInfos.Length; i++) { Type ParameterType = parameterInfos[i].ParameterType; //获取当前方法参数的类型 object Parameter = serviceProvider.GetService(ParameterType); //利用框架的服务提供对象 创建对象 MethodInjection(ParameterType, serviceProvider, Parameter); //如果有多层注入需要递归创建对象,把当前对象传入。 PropertyInjection(ParameterType, serviceProvider, Parameter); //如果有多层注入需要递归创建对象,把当前对象传入。 Parameters[i] = Parameter; //添加到参数实列数组中去 } memberInfo.Invoke(Context, Parameters); //执行方法 } } catch (Exception ex) { } } public void Release(ControllerContext context, object controller) { } } } |
4.在Startup的ConfigureServices中替换掉原有的ControllerActivator实现
1 2 3 4 5 6 7 8 9 10 11 | #region 替换掉框架自己实现的ControllerActivator //1.把控制器当做服务注册到容器中 services.AddControllersWithViews().AddControllersAsServices(); //2.找出默认的Activator var DefaultActivator = services.FirstOrDefault(m => m.ServiceType == typeof (IControllerActivator)); //3.移除默认Activator services.Remove(DefaultActivator); //4.把自己自定义的Activator添加进去 services.AddTransient<IControllerActivator, CustomControllerActivator>(); #endregion |
5.到此已经配置扩展完成,在需要属性注入和方法注入的地方加上特性就行。扩展的方法可以自动注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /// <summary> /// 属性注入 /// </summary> [PropertyInjection] private UnitOfWork unitOfWork { get ; set ; } /// <summary> /// 方法注入 /// </summary> private ILogger<UserController> Logger = null ; [MethodInjection] private void MethodInjection(ILogger<UserController> _logger) { Logger = _logger; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)