0

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?

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

Wish me luck convincing the boss to upgrade :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.