代码之家  ›  专栏  ›  技术社区  ›  Cristian Diaconescu

使用参数代理方法时Castle DynamicProxy v1异常?

  •  0
  • Cristian Diaconescu  · 技术社区  · 16 年前

    我在使用Castle dynamicProxy v1.1.5.0代理带有参数的metods时遇到问题。-我得到一个异常“索引超出了数组的边界。”

    如果我只使用没有参数的方法,或者使用dynamicProxy v2,那么一切都可以正常工作。
    不幸的是,我很难说服我项目的负责人向v2添加依赖项(我们已经在使用nhibernate附带的v1)。

    所以我的问题归结为:这可以在v1中完成吗?我用错了吗?

    这是细节。

    我实现了一种机制,它模拟继承,而不需要编译时依赖于基类。请不要问为什么,原因是丑陋的:(

    这里有一个完整的例子说明了这是如何打破的。我引用的是castle.dynamicproxy.dll(v1)。如果我更改对castle.dynamicproxy[b]2[/b].dll(+castle.core.dll)的引用,请取消注释代码开头的定义。

    抱歉,代码太长了,但我担心我会泄露一些重要的细节…
    另外:免责声明:代码示例有一些讨厌的错误!(可能比我发现的还要多:)

    //#define DynamicProxyV2
    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    
    
    #if DynamicProxyV2
    using Castle.Core.Interceptor;
    #endif
    
    using Castle.DynamicProxy;
    
    namespace ProxyTest
    {
    
        public interface IMyInterface
        {
            void Foo(object a);
            void Bar(object a);
            void Baz(object a);
        }
        public interface IParam
        {
            string Value { get;}
        }
    
        public class DefaultImplementation : IMyInterface{
            public virtual void Foo(object a) {
                Console.WriteLine("Default Foo");
                Bar(null);
            }
    
            public virtual void Bar(object a){
                Baz(null);
            }
    
            public virtual void Baz(object a){
                Console.WriteLine("Default Baz");
            }
        }
    
        class DerivedImpl : ProxyDerivedImplementation {
            public DerivedImpl(IMyInterface i_baseImpl)
                : base(i_baseImpl) { }
    
            public override void Foo(object a) {
                Console.WriteLine("Derived - Foo!");
                base.Bar(null);
            }
    
            public override void Baz(object a) {
                Console.WriteLine("Derived - Baz!");
            }
        }
    
        public class DoStuff {
            [STAThread]
            public static void Main()
            {
                Type t = typeof(DefaultImplementation);
    
                IMyInterface defaultImpl = (IMyInterface)Activator.CreateInstance(t);
                DerivedImpl derived = new DerivedImpl(defaultImpl);
                derived.Foo(null);
            }
        }
    
    
        public class ProxyDerivedImplementation : IMyInterface, IInterceptor {
            private IMyInterface m_proxy;
            public ProxyDerivedImplementation(IMyInterface i_defaultImplementation)
            {
                ProxyGenerator pg = new ProxyGenerator();
    
                Type tt = i_defaultImplementation.GetType();
                m_proxy = (IMyInterface)pg.CreateClassProxy(tt, this);
            }
    
    #if DynamicProxyV2
            #region DynProxy v2
            public void Intercept(IInvocation invocation) {
                try
                {
                    MethodInfo i_method = invocation.Method;
                    List<Type> types = new List<Type>();
    
                    foreach (ParameterInfo info in i_method.GetParameters())
                    {
                        types.Add(info.ParameterType);
                    }
                    MethodInfo method = this.GetType().GetMethod(i_method.Name, types.ToArray());
                    object[] attrs = method.GetCustomAttributes(typeof(NotOverridenAttribute), false);
                    if (attrs.Length > 0)
                    {
                        invocation.Proceed();
                    }
                    else
                    {
                        invocation.ReturnValue = method.Invoke(this, invocation.Arguments);
                    }
                }
                catch (Exception ex)
                {
                    Debug.Fail(ex.Message);
                    //return null;
                }
    
            }
            #endregion
    #else
            #region DynProxy v1
            public object Intercept(IInvocation i_invocation, params object[] args) {
                try {
                    MethodInfo proxiedMethod = i_invocation.Method;
                    List<Type> types = new List<Type>();
    
                    foreach (ParameterInfo info in proxiedMethod.GetParameters())
                    {
                        types.Add(info.ParameterType);
                    }
    
                    //find the corresponding method in the inheritance tree having this class as root
                    MethodInfo localMethod = this.GetType().GetMethod(proxiedMethod.Name, types.ToArray());
                    object[] attrs = localMethod.GetCustomAttributes(typeof(NotOverridenAttribute), false);
                    if (attrs.Length > 0)
                    {
                        //it's one of the methods in THIS class, i.e. it's not overridden
                        //-> we can't call the method in this class, because it will re-trigger this intercept
                        //   and we'd get an infinite loop
                        // => just dispatch the method to the original proxied type
                        //
                        return i_invocation.Proceed();
                    }
                    //else we have an override for this method - call it.
                    return localMethod.Invoke(this, args);
                } catch (Exception ex) {
                    Debug.Fail(ex.Message);
                    return null;
                }
            }
            #endregion
    #endif
            [NotOverriden]
            public virtual void Foo(object a) { m_proxy.Foo(a); }
    
            [NotOverriden]
            public virtual void Bar(object a) { m_proxy.Bar(a); }
    
            [NotOverriden]
            public virtual void Baz(object a) { m_proxy.Baz(a); }
        }
    
        class NotOverridenAttribute : Attribute { }
    
    }
    

    唷!那是一口。 下面是使用v1时发生的异常:

    {"Index was outside the bounds of the array."}
        [System.IndexOutOfRangeException]: {"Index was outside the bounds of the array."}
        Data: {System.Collections.ListDictionaryInternal}
        HelpLink: null
        InnerException: null
        Message: "Index was outside the bounds of the array."
        Source: "DynamicAssemblyProxyGen"
        StackTrace: "   at CProxyTypeDefaultImplementationProxyTest0.__delegate_2.Call(Object[] )\r\n   at Castle.DynamicProxy.Invocation.AbstractInvocation.Proceed(Object[] args)\r\n   at ProxyTest.ProxyDerivedImplementation.Intercept(IInvocation i_invocation, Object[] args) in D:\\My Documents\\Visual Studio 2005\\Projects\\DefaultImpl\\AddedValue\\AddedValue.cs:line 133"
        TargetSite: {System.Object Call(System.Object[])}
    

    使用v2运行时,我得到的是正确的输出:

    派生-foo! 衍生-巴兹!

    ……帮助?

    1 回复  |  直到 16 年前
        1
  •  1
  •   Krzysztof Kozmic    16 年前

    不要使用旧的dynamicproxy。它长期不受支持。如果你用的是它附带的nhibernate,我甚至不想问你用的是哪个版本的nhibernate。DPV1是 真的? 古老的