繁体   English   中英

城堡动态代理接口而不是派生类

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM