[英]Castle Dynamic Proxy of Interface and not Derived Class
namespace DynamicInterception
{
public class Calculator
{
public virtual int Div(int a, int b)
{
try
{
return a / b;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
return 0;
}
}
}
[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);
}
public class CalculatorInterceptor : Interceptor
{
protected override void ExecuteBefore(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("Start: {0}", invocation.Method.Name);
}
protected override void ExecuteAfter(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("End: {0}", invocation.Method.Name);
}
}
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
var r = c.Div(11, 0);
Console.ReadKey();
}
}
}
是否可以用interface替换public virtual int Div(int a,int b)
interface ICalculator
{
int Div(int a, int b);
}
那怎么应该看起来像代理声明?
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
如果你想为Calculator
添加一个接口并执行这两行,它将工作相同:
public interface ICalculator
{
int Div(int a, int b);
}
public class Calculator : ICalculator
{
public int Div(int a, int b)
{
try
{
return a / b;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
return 0;
}
}
}
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
但是你没有真正做任何事情 - 你仍然在为具体派生类型创建代理。 我假设你想要"CreateClassProxy<ICalculator>"
。 这是行不通的,因为CreateClassProxy
对通用约束where TClass : class
。
你所拥有的是各种CreateInterfaceProxt..
你可以尝试的方法。 但仍然像下面这样的天真执行不起作用:
ICalculator c = generator.CreateInterfaceProxyWithoutTarget<ICalculator>(new CalculatorInterceptor());
c.Div(1, 2);
它将执行,调用拦截器并在运行invocation.Proceed();
时失败invocation.Proceed();
有错误:
System.NotImplementedException这是一个DynamicProxy2错误:拦截器试图为没有目标的方法'Int32 Div(Int32,Int32)''继续'。 当调用没有目标的方法时,没有实现“继续”,拦截器有责任模仿实现(设置返回值,输出参数等)
因此,Castle指定的良好指示性(严重)错误 - 您必须以某种方式为其实现 - 或者通过在拦截器中指示它 - 通过为该接口注册Component
。
相反,你可以这样做:( 检查代码中的注释)
ProxyGenerator generator = new ProxyGenerator();
ICalculator calculator = new Calculator();
var proxyCalculator = generator.CreateInterfaceProxyWithTarget(typeof(ICalculator),calculator, new CalculatorInterceptor());
calculator.Div(1, 2); // Will execute but will not be intercepted
((ICalculator)proxyCalculator).Div(11, 0); //Will execute and will be intercepted
但在说完我上面所说的所有内容之后,如果所有这一切背后的目的是让拦截器拦截你的方法,那么只需要注册到容器的“好老”:
WindsorContainer container = new WindsorContainer();
container.Register(
Component.For<CalculatorInterceptor>(),
Component.For<ICalculator>()
.ImplementedBy<Calculator>()
.Interceptors<CalculatorInterceptor>());
var calculator = container.Resolve<ICalculator>();
calculator.Div(1, 0);
// Output:
// Start: Div
// Attempted to divide by zero
// End: Div
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.