public override bool Equals(object obj)
        {
            DelegateSignatureInfo dsi = obj as DelegateSignatureInfo;

            if (dsi == null)
            {
                return(false);
            }

            if (dsi._binder != _binder)
            {
                return(false);
            }

            if (dsi._parameters.Length != _parameters.Length)
            {
                return(false);
            }

            if (_returnType != dsi._returnType)
            {
                return(false);
            }

            for (int i = 0; i < _parameters.Length; i++)
            {
                if (dsi._parameters[i] != _parameters[i])
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Creates a delegate with a given signature that could be used to invoke this object from non-dynamic code (w/o code context).
        /// A stub is created that makes appropriate conversions/boxing and calls the object.
        /// The stub should be executed within a context of this object's language.
        /// </summary>
        /// <returns>The delegate or a <c>null</c> reference if the object is not callable.</returns>
        public static Delegate GetDelegate(object callableObject, Type delegateType)
        {
            Contract.RequiresNotNull(delegateType, "delegateType");

            Delegate result = callableObject as Delegate;

            if (result != null)
            {
                if (!delegateType.IsAssignableFrom(result.GetType()))
                {
                    throw RuntimeHelpers.SimpleTypeError(String.Format("Cannot cast {0} to {1}.", result.GetType(), delegateType));
                }

                return(result);
            }


#if FULL
            IDynamicObject dynamicObject = callableObject as IDynamicObject;
            if (dynamicObject != null)
            {
                MethodInfo invoke;

                if (!typeof(Delegate).IsAssignableFrom(delegateType) || (invoke = delegateType.GetMethod("Invoke")) == null)
                {
                    throw RuntimeHelpers.SimpleTypeError("A specific delegate type is required.");
                }

                // using IDynamicObject.LanguageContext for now, we need todo better
                Debug.Assert(dynamicObject.LanguageContext != null, "Invalid implementation");

                ParameterInfo[] parameters = invoke.GetParameters();

                dynamicObject.LanguageContext.CheckCallable(dynamicObject, parameters.Length);

                DelegateSignatureInfo signatureInfo = new DelegateSignatureInfo(
                    dynamicObject.LanguageContext.Binder,
                    invoke.ReturnType,
                    parameters
                    );

                DelegateInfo delegateInfo = _dynamicDelegateCache.GetOrCreateValue(signatureInfo,
                                                                                   delegate() {
                    // creation code
                    return(signatureInfo.GenerateDelegateStub());
                });


                result = delegateInfo.CreateDelegate(delegateType, dynamicObject);
                if (result != null)
                {
                    return(result);
                }
            }
#endif


            throw RuntimeHelpers.SimpleTypeError("Object is not callable.");
        }