仅拦截DynamicProxy的接口方法

时间:2010-01-21 14:24:30

标签: interceptor castle-dynamicproxy dynamic-proxy

我有一个像这样的界面

public interface IService
{
    void InterceptedMethod();
}

实现该接口的类,还有另一个方法

public class Service : IService
{
    public virtual void InterceptedMethod()
    {
        Console.WriteLine("InterceptedMethod");
    }

    public virtual void SomeMethod()
    {
        Console.WriteLine("SomeMethod");
    }
}

和拦截器

public class MyInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("Intercepting");
        invocation.Proceed();
    }
}

我想只拦截IService上存在的Service上的方法(即我想拦截InterceptedMethod()但不拦截SomeMethod()),但我不想使用来自IProxyGenerationHook的ShouldInterceptMethod。

我可以这样做,但由于它返回一个接口,我不能在这个对象上调用SomeMethod

var generator = new ProxyGenerator();
var proxy = generator.CreateInterfaceProxyWithTargetInterface<IService>(new Service(), new MyInterceptor());
proxy.InterceptedMethod(); // works
proxy.SomeMethod(); // Compile error, proxy is an IService

可以使用的一件事是从SomeMethod()中删除虚拟并执行此操作

var proxy = generator.CreateClassProxy<Service>(new MyInterceptor());

但我不喜欢这个解决方案。

我不喜欢使用来自IProxyGenerationHook的ShouldInterceptMethod,因为每次我更改界面时我都需要更改ShouldInterceptMethod,也有人有一天可以重构方法名称并且方法不再被截获。

还有其他方法吗?

1 个答案:

答案 0 :(得分:2)

如果要为类创建代理,则需要使用classproxy。

如果要排除某些成员,则必须使用IProxyGenerationHook。

如果您希望您的代码与接口/类成员的更改无关,就像添加或删除名称签名一样 - 而不是这样做!

我能想到的最简单的代码是这样的:

private InterfaceMap interfaceMethods = typeof(YourClass).GetInterfaceMap(typeof(YourInterface));
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
   return Array.IndexOf(interfaceMethods.ClassMethods,methodInfo)!=-1;
}