/// <summary>
        /// Gets a "meta" operation on this userdata. If a descriptor does not support this functionality,
        /// it should return "null" (not a nil).
        /// See <see cref="IUserDataDescriptor.MetaIndex" /> for further details.
        ///
        /// If a method exists marked with <see cref="MoonSharpUserDataMetamethodAttribute" /> for the specific
        /// metamethod requested, that method is returned.
        ///
        /// If the above fails, the following dispatching occur:
        ///
        /// __add, __sub, __mul, __div, __mod and __unm are dispatched to C# operator overloads (if they exist)
        /// __eq is dispatched to System.Object.Equals.
        /// __lt and __le are dispatched IComparable.Compare, if the type implements IComparable or IComparable{object}
        /// __len is dispatched to Length and Count properties, if those exist.
        /// __iterator is handled if the object implements IEnumerable or IEnumerator.
        /// __tonumber is dispatched to implicit or explicit conversion operators to standard numeric types.
        /// __tobool is dispatched to an implicit or explicit conversion operator to bool. If that fails, operator true is used.
        ///
        /// <param name="script">The script originating the request</param>
        /// <param name="obj">The object (null if a static request is done)</param>
        /// <param name="metaname">The name of the metamember.</param>
        /// </summary>
        /// <returns></returns>
        public virtual DynValue MetaIndex(Script script, object obj, string metaname)
        {
            StandardUserDataOverloadedMethodDescriptor desc = m_MetaMethods.GetOrDefault(metaname);

            if (desc != null)
            {
                return(desc.GetCallbackAsDynValue(script, obj));
            }

            switch (metaname)
            {
            case "__add":
                return(DispatchMetaOnMethod(script, obj, "op_Addition"));

            case "__sub":
                return(DispatchMetaOnMethod(script, obj, "op_Subtraction"));

            case "__mul":
                return(DispatchMetaOnMethod(script, obj, "op_Multiply"));

            case "__div":
                return(DispatchMetaOnMethod(script, obj, "op_Division"));

            case "__mod":
                return(DispatchMetaOnMethod(script, obj, "op_Modulus"));

            case "__unm":
                return(DispatchMetaOnMethod(script, obj, "op_UnaryNegation"));

            case "__eq":
                return(MultiDispatchEqual(script, obj));

            case "__lt":
                return(MultiDispatchLessThan(script, obj));

            case "__le":
                return(MultiDispatchLessThanOrEqual(script, obj));

            case "__len":
                return(TryDispatchLength(script, obj));

            case "__tonumber":
                return(TryDispatchToNumber(script, obj));

            case "__tobool":
                return(TryDispatchToBool(script, obj));

            case "__iterator":
                return(ClrToScriptConversions.EnumerationToDynValue(script, obj));

            default:
                return(null);
            }
        }
        private DynValue DispatchMetaOnMethod(Script script, object obj, string methodName)
        {
            StandardUserDataOverloadedMethodDescriptor desc = m_Methods.GetOrDefault(methodName);

            if (desc != null)
            {
                return(desc.GetCallbackAsDynValue(script, obj));
            }
            else
            {
                return(null);
            }
        }