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

如何获取无目标创建的Castle动态代理的接口类型

解决Castle DynamicProxy拦截器中识别代理目标接口的问题

方法一:直接检查代理实例的类型

Castle生成的代理类会直接实现你指定的目标接口,所以可以通过判断invocation.Proxy是否为目标接口的实例来区分:

public class Proxy : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (invocation.Proxy is IFoo)
        {
            // 当前代理基于IFoo生成
            Console.WriteLine("处理IFoo代理的调用");
        }
        else if (invocation.Proxy is IFooBase)
        {
            // 当前代理基于IFooBase生成
            Console.WriteLine("处理IFooBase代理的调用");
        }
        
        invocation.Proceed(); // 执行原方法逻辑
    }
}

这个方法简单直接,适配你的场景——IFoo继承自IFooBase,但IFooBase的代理不会实现IFoo,判断顺序不影响结果。

方法二:通过代理生成选项传递自定义标记

如果场景更复杂(比如多层接口继承、需要传递额外元数据),可以在创建代理时通过ProxyGenerationOptions附加自定义标记,再在拦截器中读取:

步骤1:定义自定义标记属性

[AttributeUsage(AttributeTargets.Class)]
public class ProxyTargetInterfaceAttribute : Attribute
{
    public Type TargetInterface { get; }

    public ProxyTargetInterfaceAttribute(Type targetInterface)
    {
        TargetInterface = targetInterface;
    }
}

步骤2:创建代理时附加标记

var generator = new ProxyGenerator();
var proxy = new Proxy();

// 创建IFooBase代理
var optionsBase = new ProxyGenerationOptions();
optionsBase.SetCustomAttribute(new ProxyTargetInterfaceAttribute(typeof(IFooBase)));
var fooBase = generator.CreateInterfaceProxyWithoutTarget<IFooBase>(optionsBase, proxy);

// 创建IFoo代理
var optionsFoo = new ProxyGenerationOptions();
optionsFoo.SetCustomAttribute(new ProxyTargetInterfaceAttribute(typeof(IFoo)));
var foo = generator.CreateInterfaceProxyWithoutTarget<IFoo>(optionsFoo, proxy);

步骤3:拦截器中读取标记

public class Proxy : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        var targetAttr = invocation.Proxy.GetType()
            .GetCustomAttribute<ProxyTargetInterfaceAttribute>();
        
        if (targetAttr?.TargetInterface == typeof(IFoo))
        {
            // 处理IFoo代理
        }
        else if (targetAttr?.TargetInterface == typeof(IFooBase))
        {
            // 处理IFooBase代理
        }
        
        invocation.Proceed();
    }
}

这个方法更灵活,不依赖接口继承关系,适合多接口、复杂代理场景。

关键注意点

  • 不要依赖invocation.Method.DeclaringType:因为DoSomething定义在IFooBase中,无论代理基于哪个接口,这个属性都会返回IFooBase,这就是你之前遇到的核心问题。
  • 避免依赖Castle内部代理类命名:比如Castle.Proxies.IFooProxy这类命名属于内部实现,不同版本可能变化,稳定性差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:43:15