如何通过反射向Action列表添加方法?.NET实体创建日志场景
如何通过反射将LogAugmenter.LogCreation添加到业务类的PostCreationAugmenters列表中?
我有大量继承自泛型基类Business<T>的业务类,希望为它们动态添加实体创建后的日志记录逻辑——具体来说,就是把LogAugmenter.LogCreation方法添加到每个业务类的静态PostCreationAugmenters列表中。以下是我的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; var businessClasses = typeof(IEntity) .Assembly .GetTypes() .ToList() .Where(i => i.BaseType != null) .Where(i => i.BaseType.Name.StartsWith("Business")) .ToList(); Console.WriteLine(businessClasses.Count); foreach (var businessClass in businessClasses) { var postCreationAugmenters = businessClass.GetField("PostCreationAugmenters", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static).GetValue(null); // how can I add the LogAugmenter.LogCreation to the postCreationAugmenters list? } public static class LogAugmenter { public static void LogCreation(IEntity entity) { } } public interface IEntity { long Id { get; set; } } public class Blog : IEntity { public long Id { get; set; } } public class Business<T> where T : IEntity { public static List<Action<T>> PostCreationAugmenters = new List<Action<T>>(); public T Create(T entity) { // Inserting the model inside the database and returning it with the assigned Id foreach (var augmenter in PostCreationAugmenters) { augmenter.Invoke(entity); } return entity; } } public class BlogBusiness : Business<Blog> { }
解决方案
要实现需求,需要通过反射完成三个核心步骤:提取泛型参数、转换匹配委托、添加到目标列表。修改后的循环代码如下:
foreach (var businessClass in businessClasses) { // 1. 获取基类的泛型参数T(如Blog) var genericBaseType = businessClass.BaseType; var entityType = genericBaseType.GetGenericArguments()[0]; // 2. 获取PostCreationAugmenters静态字段 var field = genericBaseType.GetField("PostCreationAugmenters", BindingFlags.Public | BindingFlags.Static); var augmenterList = field.GetValue(null) as IList; // 3. 将LogCreation转换为匹配的Action<T>委托 var logMethod = typeof(LogAugmenter).GetMethod("LogCreation", BindingFlags.Public | BindingFlags.Static); var actionDelegate = Delegate.CreateDelegate( typeof(Action<>).MakeGenericType(entityType), logMethod ); // 4. 添加到列表 augmenterList.Add(actionDelegate); }
关键细节说明
- 直接从泛型基类
Business<T>获取静态字段:因为静态字段属于泛型构造体(如Business<Blog>),而非子类BlogBusiness - 使用
Delegate.CreateDelegate完成委托类型转换:由于T实现了IEntity,将Action<IEntity>转为Action<T>是安全的 - 借助
IList接口统一处理:避免为每种实体类型编写特定的类型逻辑
完整可运行代码
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; var businessClasses = typeof(IEntity) .Assembly .GetTypes() .Where(i => i.BaseType != null && i.BaseType.IsGenericType && i.BaseType.GetGenericTypeDefinition() == typeof(Business<>)) .ToList(); Console.WriteLine($"找到{businessClasses.Count}个业务类"); foreach (var businessClass in businessClasses) { var genericBaseType = businessClass.BaseType; var entityType = genericBaseType.GetGenericArguments()[0]; var field = genericBaseType.GetField("PostCreationAugmenters", BindingFlags.Public | BindingFlags.Static); var augmenterList = field.GetValue(null) as IList; var logMethod = typeof(LogAugmenter).GetMethod("LogCreation", BindingFlags.Public | BindingFlags.Static); var actionDelegate = Delegate.CreateDelegate( typeof(Action<>).MakeGenericType(entityType), logMethod ); augmenterList.Add(actionDelegate); } // 测试日志逻辑 var blogBusiness = new BlogBusiness(); var blog = new Blog { Id = 1 }; blogBusiness.Create(blog); public static class LogAugmenter { public static void LogCreation(IEntity entity) { Console.WriteLine($"已记录实体创建日志:{entity.GetType().Name}(ID:{entity.Id})"); } } public interface IEntity { long Id { get; set; } } public class Blog : IEntity { public long Id { get; set; } } public class Business<T> where T : IEntity { public static List<Action<T>> PostCreationAugmenters = new List<Action<T>>(); public T Create(T entity) { // 模拟数据库插入逻辑 foreach (var augmenter in PostCreationAugmenters) { augmenter.Invoke(entity); } return entity; } } public class BlogBusiness : Business<Blog> { }
内容的提问来源于stack exchange,提问作者Sharif Rezvani
相关产品推荐
相关产品推荐

