如何在Castle.DynamicProxy中使用IInterceptor?

时间:2015-02-14 18:17:07

标签: c# interceptor castle-dynamicproxy dynamic-proxy interception

我写了一个这样的例子

简单计算器类:

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

实施了由DynamicProxy提供的“IInterceptor”

 [Serializable]
public abstract class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        ExecuteBefore(invocation);
        invocation.Proceed();
        ExecuteAfter(invocation);

    }
    protected abstract void ExecuteAfter(IInvocation invocation);
    protected abstract void ExecuteBefore(IInvocation invocation);
}

创建了一个Interceptor类,并继承自“Interceptor”类

    public class CalculatorInterceptor : Interceptor
{
    protected override void ExecuteBefore(Castle.DynamicProxy.IInvocation invocation)
    {
        Console.WriteLine("Start");
    }

    protected override void ExecuteAfter(Castle.DynamicProxy.IInvocation invocation)
    {
        Console.WriteLine("End");
    }
}

但是当我用它时不工作!!!

static void Main(string[] args)
    {
        ProxyGenerator generator = new ProxyGenerator();
        Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
        var r = c.Add(11, 22);
        Console.WriteLine(r);
        Console.ReadKey();
    }

我除了看到这样的事情:

START
33
END

但只显示

33

我如何纠正它?!

3 个答案:

答案 0 :(得分:15)

尝试将方法Add设为虚拟。

public class Calculator
{
    public virtual int Add(int a, int b)
    {
        return a + b;
    }
}

代理生成器创建一个继承Calculator的新类。因此,方法Add获得覆盖以使拦截成为可能。

答案 1 :(得分:3)

另一个选择是制作ICalculator接口

public interface ICalculator
{
   int Add(int a, int b);
}

并从此界面继承您的类

public class Calculator : ICalculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

您的动态代理将使用 CreateInterfaceProxyWithTarget 方法

var proxyGenerator = new ProxyGenerator();

ICalculator calculator = new Calculator()

var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(
    calculator,
    ProxyGenerationOptions.Default,
    new CalculatorInterceptor());

Console.WriteLine(proxy.Add(1, 2));

这可以从你的Calculator类中删除虚拟,在我看来这是一个糟糕的设计,除非你有理由在将来覆盖这个方法。

答案 2 :(得分:0)

您必须使用正确的重载并传入目标对象和您想要使用的拦截器。方法应如下所示:

var proxy = generator.CreateClassProxy<Calculator>(new Calculator(), new CalculatorInterceptor() );