A19*_*919 6 c# proxy castle-windsor castle-dynamicproxy
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以public virtual int Div(int a,int b)
用接口替换
interface ICalculator
{
int Div(int a, int b);
}
Run Code Online (Sandbox Code Playgroud)
那怎么应该看起来像代理声明?
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
Run Code Online (Sandbox Code Playgroud)
如果你想要添加一个接口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());
Run Code Online (Sandbox Code Playgroud)
但是你没有真正做任何事情 - 你仍然在为具体派生类型创建代理.我假设你想要类似的东西"CreateClassProxy<ICalculator>".这将无效,因为它CreateClassProxy具有通用约束where TClass : class.
你所拥有的是CreateInterfaceProxt..你可以尝试的各种方法.但仍然像下面这样的天真执行不起作用:
ICalculator c = generator.CreateInterfaceProxyWithoutTarget<ICalculator>(new CalculatorInterceptor());
c.Div(1, 2);
Run Code Online (Sandbox Code Playgroud)
它将执行,调用拦截器并在运行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
Run Code Online (Sandbox Code Playgroud)
但在说完我上面所说的所有内容之后,如果所有这一切背后的目的是让拦截器拦截你的方法,那么只需要注册到容器的"好老":
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1047 次 |
| 最近记录: |