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();
}
}
}
是否可以替换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());
答案 0 :(得分:5)
如果要向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();
时出错,并显示错误:
System.NotImplementedException这是一个DynamicProxy2错误: 拦截器试图“继续”#39;方法&#39; Int32 Div(Int32, INT32)&#39;没有目标。在没有目标的情况下调用方法 没有实现“继续”#39;它是责任 拦截器模仿实现(设置返回值,输出 论据等)
因此,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
但是在说完我上面所说的所有内容之后,如果所有这一切背后的目的是让一个拦截器拦截你的方法,那么只需要一个好老的&#34;注册到容器:
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