如何在Castle.DynamicProxy中使用IInterceptor?

use*_*878 17 c# castle-dynamicproxy dynamic-proxy interceptor interception

我写了一个这样的例子

简单计算器类:

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

实现了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);
}
Run Code Online (Sandbox Code Playgroud)

创建了一个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");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我用它不工作!

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();
    }
Run Code Online (Sandbox Code Playgroud)

我除外看到这样的事情:

START
33
END
Run Code Online (Sandbox Code Playgroud)

但只显示

33
Run Code Online (Sandbox Code Playgroud)

我怎么纠正它?!

Axe*_*eer 16

尝试将该方法设为Add虚拟.

public class Calculator
{
    public virtual int Add(int a, int b)
    {
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @ user3153878拦截器在"Add"调用之前和之后执行,但是之后将结果写入控制台(执行之前 - >执行添加 - >执行之后 - >写入结果).如果在"Add"方法中进行控制台调用,则应获得所需的结果. (3认同)

小智 5

另一个选择是制作一个ICalculator接口

public interface ICalculator
{
   int Add(int a, int b);
}
Run Code Online (Sandbox Code Playgroud)

并从此接口继承您的课程

public class Calculator : ICalculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

var proxyGenerator = new ProxyGenerator();

ICalculator calculator = new Calculator()

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

Console.WriteLine(proxy.Add(1, 2));
Run Code Online (Sandbox Code Playgroud)

这摆脱了您的Calculator类中的虚函数,我认为这是不好的设计,除非您将来有理由重写该方法。