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

发布于 2024-08-20 00:21:02 字数 6252 浏览 9 评论 0原文

我在使用 Castle DynamicProxy v1.1.5.0 代理带有参数的方法时遇到问题。 - 我收到异常“索引超出数组范围”。

如果我只使用不带参数的方法,或者 DynamicProxy v2,一切正常。
不幸的是,我很难说服我的项目的领导添加对 v2 的依赖(我们已经在使用 v1,因为它随 NHibernate 一起提供)。

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

这是实质内容。

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

这是一个完整的示例,显示了这是如何中断的。我引用的是 Castle.DynamicProxy.dll (v1)。如果我更改对 Castle.DynamicProxy[b]2[ 的引用/b].dll (+ Castle.Core.dll),取消注释代码开头的#define。

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

//#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! 派生 - Baz!

...帮助?

I'm having problems proxying metods with parameters using Castle DynamicProxy v1.1.5.0. - I get the exception "Index was outside the bounds of the array."

If I only use methods with no parameters, OR DynamicProxy v2, everything works ok.
Unfortunately, I'm having trouble convincing the leads on my project to add a dependency to v2 (we're already using v1 as it comes with NHibernate).

So my question boils down to: can this be done in v1? Am I using it wrong?

Here's the nitty-gritty.

I've implemented a mechanism that simulates inheritance without having compile-time dependencies to the base class. Pleeease don't ask why, the reasons are ugly :(

Here is a complete example showing how this breaks. I'm referencing Castle.DynamicProxy.dll (v1). If I change the references to Castle.DynamicProxy[b]2[/b].dll (+ Castle.Core.dll), un-comment the #define at the beginning of the code.

Sorry for the long-ish code, but I was afraid I might let out some vital detail...
Also: DISCLAIMER: The code sample has some NASTY bugs! (Probably more than I found, too :)

//#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 { }

}

Whew! That's a mouthful.
Here's the exception that occurs when using 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[])}

When running with v2, all I get is the correct output:

Derived - Foo!
Derived - Baz!

...Help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

原野 2024-08-27 00:21:02

不要使用旧的 DynamicProxy。长期以来一直不受支持。如果你使用的是NHibernate自带的,我什至不想问你使用的是哪个版本的NHibernate。 DPv1确实很旧

don't use old DynamicProxy. It is long unsupported. If you're using NHibernate that comes with it, I don't even want to ask which version of NHibernate you're using. DPv1 is really old

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文