【问题标题】:Castle Dynamic Proxy of Interface and not Derived Class接口的城堡动态代理而不是派生类
【发布时间】:2016-12-25 03:08:08
【问题描述】:
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());

【问题讨论】:

    标签: c# proxy castle-windsor castle-dynamicproxy


    【解决方案1】:

    如果您想向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&lt;ICalculator&gt;" 这样的东西。这行不通,因为CreateClassProxywhere TClass : class 有一个通用约束。

    您所拥有的是可以尝试的各种CreateInterfaceProxt.. 方法。但是像下面这样幼稚的执行仍然是行不通的:

    ICalculator c = generator.CreateInterfaceProxyWithoutTarget<ICalculator>(new CalculatorInterceptor());
    c.Div(1, 2);
    

    它将执行,调用拦截器并在运行invocation.Proceed();时失败并出现错误:

    System.NotImplementedException 这是一个 DynamicProxy2 错误: 拦截器试图为方法“Int32 Div(Int32, Int32)' 没有目标。当调用没有目标的方法时 不是“继续”的实施,它是 模仿实现的拦截器(设置返回值,out 论据等)

    因此,正如 Castle 的良好指示性(严重)错误所指定的那样 - 您必须以某种方式为其实现 - 或者通过自己在拦截器中指示它 - 为该接口注册 Component

    相反,您可以这样做:(检查代码中的 cmets)

    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
    

    【讨论】:

      猜你喜欢
      • 2018-03-14
      • 2011-03-28
      • 2010-11-28
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多