/// <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); }
/// <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)); } } }
/// <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)); }