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

如何使用DispatchProxy拦截标记自定义特性的方法?

实现基于DispatchProxy的特性标记方法拦截

1. 完善InterceptorProxy的核心拦截逻辑

在你的InterceptorProxy的Invoke方法中增加特性判断,仅对标记了DispachedAttribute的方法执行拦截逻辑,未标记的直接调用原方法:

public class InterceptorProxy<T> : DispatchProxy
{
    private T _target;
    // 可自定义拦截处理逻辑的委托
    private Action<MethodInfo, object[], object> _interceptHandler;

    public static T Create(T target, Action<MethodInfo, object[], object> interceptHandler)
    {
        var proxy = Create<T, InterceptorProxy<T>>() as InterceptorProxy<T>;
        proxy._target = target;
        proxy._interceptHandler = interceptHandler;
        return proxy as T;
    }

    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        // 检查当前方法是否标记了目标特性
        var isDispached = targetMethod.GetCustomAttributes(typeof(DispachedAttribute), inherit: true).Any();
        object result;

        if (isDispached)
        {
            // 拦截前置操作,比如日志、参数校验
            Console.WriteLine($"[拦截前置] 方法{targetMethod.Name}开始执行");
            
            // 调用原始方法
            result = targetMethod.Invoke(_target, args);
            
            // 拦截后置操作,比如结果处理、性能统计
            _interceptHandler?.Invoke(targetMethod, args, result);
            Console.WriteLine($"[拦截后置] 方法{targetMethod.Name}执行完成");
        }
        else
        {
            // 未标记特性,直接执行原方法
            result = targetMethod.Invoke(_target, args);
        }

        return result;
    }
}

2. 封装代理工厂实现一键创建代理

写一个静态工厂类,避免重复编写代理创建代码,让业务代码可以快速拿到带拦截逻辑的实例:

public static class ProxyFactory
{
    public static T CreateProxy<T>(T target) where T : class
    {
        return InterceptorProxy<T>.Create(target, (method, args, result) =>
        {
            // 这里可以自定义具体的拦截逻辑,比如记录方法执行日志
            Console.WriteLine($"[拦截记录] 方法{method.Name},参数:{string.Join(", ", args)},返回值:{result}");
        });
    }
}

3. 普通类的拦截自动生效

业务代码中直接通过工厂创建实例,拿到的就是已开启拦截的代理对象:

public class TaskService
{
    [Dispached]
    public void Run()
    {
        Console.WriteLine("执行Run业务逻辑");
    }

    public void NormalMethod()
    {
        Console.WriteLine("这个方法不会被拦截");
    }
}

// 使用示例
var service = ProxyFactory.CreateProxy(new TaskService());
service.Run(); // 触发拦截
service.NormalMethod(); // 无拦截

4. MVC控制器的拦截自动生效

如果是ASP.NET MVC控制器,结合依赖注入实现自动注入代理对象:

4.1 在DI容器中注册代理逻辑

在Program.cs中替换原始服务的注册逻辑,让容器返回代理对象:

builder.Services.AddScoped<TaskService>();
// 注册代理版本的服务
builder.Services.AddScoped<ITaskService>(sp =>
{
    var originalService = sp.GetRequiredService<TaskService>();
    return ProxyFactory.CreateProxy(originalService);
});

4.2 控制器构造注入

控制器中直接注入接口,拿到的就是带拦截逻辑的代理实例,标记了特性的方法自动触发拦截:

public class HomeController : Controller
{
    private readonly ITaskService _taskService;

    public HomeController(ITaskService taskService)
    {
        _taskService = taskService;
    }

    public IActionResult Index()
    {
        _taskService.Run(); // 自动执行拦截逻辑
        return View();
    }
}

关键注意事项

  • 被代理的类不能是sealed(密封类),DispatchProxy需要生成继承自目标类的代理子类。
  • 如果要拦截控制器自身的方法(而非依赖服务),可以自定义控制器激活器,在创建控制器实例时通过ProxyFactory生成代理对象。

内容的提问来源于stack exchange,提问作者barteloma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:03:32