You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 05:15:23