如何在Castle.DynamicProxy中使用IInterceptor?
How use IInterceptor in Castle.DynamicProxy?
我写了一个这样的例子
简单计算器class:
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
实现了 "IInterceptor" 由 DynamicProxy
提供
[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);
}
创建了一个拦截器 class 并继承自 "Interceptor" class
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
我该如何更正它?!
您必须使用正确的重载并传入您希望使用的目标对象和拦截器。方法应如下所示:
var proxy = generator.CreateClassProxy<Calculator>(new Calculator(), new CalculatorInterceptor() );
尝试使方法 Add
成为虚拟方法。
public class Calculator
{
public virtual int Add(int a, int b)
{
return a + b;
}
}
代理生成器创建一个新的 class 继承 Calculator
。因此,方法 Add
获得重写以使拦截成为可能。
另一种选择是制作一个 ICalculator 界面
public interface ICalculator
{
int Add(int a, int b);
}
并从此接口继承您的class
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));
这从您的计算器中删除了虚拟 class,在我看来这是糟糕的设计,除非您将来有理由重写该方法。
我写了一个这样的例子
简单计算器class:
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
实现了 "IInterceptor" 由 DynamicProxy
提供 [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);
}
创建了一个拦截器 class 并继承自 "Interceptor" class
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
我该如何更正它?!
您必须使用正确的重载并传入您希望使用的目标对象和拦截器。方法应如下所示:
var proxy = generator.CreateClassProxy<Calculator>(new Calculator(), new CalculatorInterceptor() );
尝试使方法 Add
成为虚拟方法。
public class Calculator
{
public virtual int Add(int a, int b)
{
return a + b;
}
}
代理生成器创建一个新的 class 继承 Calculator
。因此,方法 Add
获得重写以使拦截成为可能。
另一种选择是制作一个 ICalculator 界面
public interface ICalculator
{
int Add(int a, int b);
}
并从此接口继承您的class
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));
这从您的计算器中删除了虚拟 class,在我看来这是糟糕的设计,除非您将来有理由重写该方法。