如何在Castle.DynamicProxy中使用IInterceptor?

23

我写了一个像这样的例子

简单计算器类:

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"类

    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个回答

24

尝试将方法 Add 设为虚拟方法。

public class Calculator
{
    public virtual int Add(int a, int b)
    {
        return a + b;
    }
}
代理生成器会创建一个继承 Calculator 的新类。因此,方法 Add 被重写以实现拦截功能。

1
是的,看起来没问题,但有一个问题,结果是START END 33。我该如何正确设置Before和After,以便看到像这样的结果START 33 END?我能否在拦截器类中更正以进行正确的方法调用?!! - user3153878
3
@user3153878,拦截器在Add方法调用之前和之后都会执行,但你在之后将结果写入控制台(执行顺序:执行之前 -> 执行Add -> 执行之后 -> 写入结果)。如果你在Add方法内部进行控制台调用,就可以得到所需的结果。 - Axel Heer

14
另一个选择是创建一个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));

在我看来,除非您有将来需要覆盖该方法的原因,否则从您的计算器类中移除虚拟方法是不好的设计。


0

你必须使用正确的重载并传入目标对象和你希望使用的拦截器。方法应该看起来像这样:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接