예제 #1
0
        /// <summary>
        /// Fills the member list.
        /// </summary>
        private void FillMemberList()
        {
            HashSet <string> membersToIgnore = new HashSet <string>(
                Framework.Do.GetCustomAttributes(this.Type, typeof(MoonSharpHideMemberAttribute), true)
                .OfType <MoonSharpHideMemberAttribute>()
                .Select(a => a.MemberName)
                );

            Type type = this.Type;

            if (AccessMode == InteropAccessMode.HideMembers)
            {
                return;
            }

            if (!type.IsDelegateType())
            {
                // add declared constructors
                foreach (ConstructorInfo ci in Framework.Do.GetConstructors(type))
                {
                    if (membersToIgnore.Contains("__new"))
                    {
                        continue;
                    }

                    AddMember("__new", MethodMemberDescriptor.TryCreateIfVisible(ci, this.AccessMode));
                }

                // valuetypes don't reflect their empty ctor.. actually empty ctors are a perversion, we don't care and implement ours
                if (Framework.Do.IsValueType(type) && !membersToIgnore.Contains("__new"))
                {
                    AddMember("__new", new ValueTypeDefaultCtorMemberDescriptor(type));
                }
            }


            // add methods to method list and metamethods
            foreach (MethodInfo mi in Framework.Do.GetMethods(type))
            {
                if (membersToIgnore.Contains(mi.Name))
                {
                    continue;
                }

                MethodMemberDescriptor md = MethodMemberDescriptor.TryCreateIfVisible(mi, this.AccessMode);

                if (md != null)
                {
                    if (!MethodMemberDescriptor.CheckMethodIsCompatible(mi, false))
                    {
                        continue;
                    }

                    // transform explicit/implicit conversions to a friendlier name.
                    string name = mi.Name;
                    if (mi.IsSpecialName && (mi.Name == SPECIALNAME_CAST_EXPLICIT || mi.Name == SPECIALNAME_CAST_IMPLICIT))
                    {
                        name = mi.ReturnType.GetConversionMethodName();
                    }

                    AddMember(name, md);

                    foreach (string metaname in mi.GetMetaNamesFromAttributes())
                    {
                        AddMetaMember(metaname, md);
                    }
                }
            }

            // get properties
            foreach (PropertyInfo pi in Framework.Do.GetProperties(type))
            {
                if (pi.IsSpecialName || pi.GetIndexParameters().Any() || membersToIgnore.Contains(pi.Name))
                {
                    continue;
                }

                AddMember(pi.Name, PropertyMemberDescriptor.TryCreateIfVisible(pi, this.AccessMode));
            }

            // get fields
            foreach (FieldInfo fi in Framework.Do.GetFields(type))
            {
                if (fi.IsSpecialName || membersToIgnore.Contains(fi.Name))
                {
                    continue;
                }

                AddMember(fi.Name, FieldMemberDescriptor.TryCreateIfVisible(fi, this.AccessMode));
            }

            // get events
            foreach (EventInfo ei in Framework.Do.GetEvents(type))
            {
                if (ei.IsSpecialName || membersToIgnore.Contains(ei.Name))
                {
                    continue;
                }

                AddMember(ei.Name, EventMemberDescriptor.TryCreateIfVisible(ei, this.AccessMode));
            }

            // get nested types and create statics
            foreach (Type nestedType in Framework.Do.GetNestedTypes(type))
            {
                if (membersToIgnore.Contains(nestedType.Name))
                {
                    continue;
                }

                if (!Framework.Do.IsGenericTypeDefinition(nestedType))
                {
                    if (Framework.Do.IsNestedPublic(nestedType) || Framework.Do.GetCustomAttributes(nestedType, typeof(MoonSharpUserDataAttribute), true).Length > 0)
                    {
                        var descr = UserData.RegisterType(nestedType, this.AccessMode);

                        if (descr != null)
                        {
                            AddDynValue(nestedType.Name, UserData.CreateStatic(nestedType));
                        }
                    }
                }
            }

            if (!membersToIgnore.Contains("[this]"))
            {
                if (Type.IsArray)
                {
                    int rank = Type.GetArrayRank();

                    ParameterDescriptor[] get_pars = new ParameterDescriptor[rank];
                    ParameterDescriptor[] set_pars = new ParameterDescriptor[rank + 1];

                    for (int i = 0; i < rank; i++)
                    {
                        get_pars[i] = set_pars[i] = new ParameterDescriptor("idx" + i.ToString(), typeof(int));
                    }

                    set_pars[rank] = new ParameterDescriptor("value", Type.GetElementType());

                    AddMember(SPECIALNAME_INDEXER_SET, new ArrayMemberDescriptor(SPECIALNAME_INDEXER_SET, true, set_pars));
                    AddMember(SPECIALNAME_INDEXER_GET, new ArrayMemberDescriptor(SPECIALNAME_INDEXER_GET, false, get_pars));
                }
                else if (Type == typeof(Array))
                {
                    AddMember(SPECIALNAME_INDEXER_SET, new ArrayMemberDescriptor(SPECIALNAME_INDEXER_SET, true));
                    AddMember(SPECIALNAME_INDEXER_GET, new ArrayMemberDescriptor(SPECIALNAME_INDEXER_GET, false));
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Checks if the event is compatible with a standard descriptor
        /// </summary>
        /// <param name="ei">The EventInfo.</param>
        /// <param name="throwException">if set to <c>true</c> an exception with the proper error message is thrown if not compatible.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">
        /// Thrown if throwException is <c>true</c> and one of this applies:
        /// The event is declared in a value type
        /// or
        /// The event does not have both add and remove methods
        /// or
        /// The event handler type doesn't implement a public Invoke method
        /// or
        /// The event handler has a return type which is not System.Void
        /// or
        /// The event handler has more than MAX_ARGS_IN_DELEGATE parameters
        /// or
        /// The event handler has a value type parameter or a by ref parameter
        /// or
        /// The event handler signature is not a valid method according to <see cref="MethodMemberDescriptor.CheckMethodIsCompatible"/>
        /// </exception>
        public static bool CheckEventIsCompatible(EventInfo ei, bool throwException)
        {
            if (Framework.Do.IsValueType(ei.DeclaringType))
            {
                if (throwException)
                {
                    throw new ArgumentException("Events are not supported on value types");
                }
                return(false);
            }

            if ((Framework.Do.GetAddMethod(ei) == null) || (Framework.Do.GetRemoveMethod(ei) == null))
            {
                if (throwException)
                {
                    throw new ArgumentException("Event must have add and remove methods");
                }
                return(false);
            }

            MethodInfo invoke = Framework.Do.GetMethod(ei.EventHandlerType, "Invoke");

            if (invoke == null)
            {
                if (throwException)
                {
                    throw new ArgumentException("Event handler type doesn't seem to be a delegate");
                }
                return(false);
            }

            if (!MethodMemberDescriptor.CheckMethodIsCompatible(invoke, throwException))
            {
                return(false);
            }

            if (invoke.ReturnType != typeof(void))
            {
                if (throwException)
                {
                    throw new ArgumentException("Event handler cannot have a return type");
                }
                return(false);
            }

            ParameterInfo[] pars = invoke.GetParameters();

            if (pars.Length > MAX_ARGS_IN_DELEGATE)
            {
                if (throwException)
                {
                    throw new ArgumentException(string.Format("Event handler cannot have more than {0} parameters", MAX_ARGS_IN_DELEGATE));
                }
                return(false);
            }

            foreach (ParameterInfo pi in pars)
            {
                if (Framework.Do.IsValueType(pi.ParameterType))
                {
                    if (throwException)
                    {
                        throw new ArgumentException("Event handler cannot have value type parameters");
                    }
                    return(false);
                }
                else if (pi.ParameterType.IsByRef)
                {
                    if (throwException)
                    {
                        throw new ArgumentException("Event handler cannot have by-ref type parameters");
                    }
                    return(false);
                }
            }

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Creates a callback DynValue starting from a MethodInfo.
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="mi">The mi.</param>
        /// <param name="obj">The object.</param>
        /// <returns></returns>
        public static DynValue CreateCallbackDynValue(Script script, MethodInfo mi, object obj = null)
        {
            var desc = new MethodMemberDescriptor(mi);

            return(desc.GetCallbackAsDynValue(script, obj));
        }