public static MondFunction CreateConstructorShim(Type type, MondValue prototype, MondBindingOptions options) => delegate(MondState state, MondValue[] args) { var target = BindingUtils.GetTarget <ConstructorInfo>( type, null, args, BindingFlags.Public | BindingFlags.Instance, options); var values = TypeConverter.MarshalToClr(args, target.Types, state, options); return(new MondValue(state) { UserData = target.Method.Invoke(values), Prototype = prototype }); };
private static ReflectedMember <T> GetTarget <T>( Type type, string name, MondValue[] args, BindingFlags flags, MondBindingOptions options) where T : MemberInfo { if ((typeof(T) != typeof(ConstructorInfo)) && (typeof(T) != typeof(MethodInfo))) { throw new ArgumentException("Generic argument must be either ConstructorInfo or MethodInfo", "T"); } var matcher = BindingUtils.CreateTargetMatcher <T>(args, name, options); var members = null as MemberInfo[]; if (typeof(T) == typeof(ConstructorInfo)) { members = type.GetConstructors(flags); } else if (typeof(T) == typeof(MethodInfo)) { members = type.GetMethods(flags); } // ReSharper disable once AssignNullToNotNullAttribute var matched = members.Select(m => matcher((T)m)) .Where(m => m.Matched); var reflectedMembers = matched as ReflectedMember <T>[] ?? matched.ToArray(); if (reflectedMembers.Length > 1) { throw new AmbiguousMatchException( $"More than one {( typeof( T ) == typeof( ConstructorInfo ) ? "constructor" : "method" )}" + $" in {type.GetName()} matches the argument list for {name}"); } if (reflectedMembers.Length == 0) { throw new MissingMethodException( $"No {( typeof( T ) == typeof( ConstructorInfo ) ? "constructor" : "method" )} in" + $" {type.GetName()} matches the argument list for {name}"); } return(reflectedMembers.First()); }
public static MondInstanceFunction CreateInstanceOverloadGroupShim( IEnumerable <MethodInfo> methods, MondBindingOptions options) => delegate(MondState state, MondValue instance, MondValue[] args) { // Remove the object instance from the argument list. // This is primarily to prevent argument mismatch exceptions // when the Mond runtime tries to dispatch a metamethod. if ((args != null) && (args.Length >= 1) && (args[0] == instance)) { args = args.Skip(1).ToArray(); } var matcher = BindingUtils.CreateTargetMatcher <MethodInfo>(args, null, options); var matched = methods.Select(matcher).Where(m => m.Matched); var reflectedMembers = matched as ReflectedMember <MethodInfo>[] ?? matched.ToArray(); if (reflectedMembers.Length > 1) { throw new AmbiguousMatchException( "More than one delegate in the invokation list matches the argument list"); } if (reflectedMembers.Length == 0) { throw new MissingMethodException( "No delegate in the invokation list matches the argument list"); } var target = reflectedMembers[0]; var values = TypeConverter.MarshalToClr(args, target.Types, state, options); var result = target.Method.Invoke(instance.UserData, values); if (target.Method.ReturnType == typeof(void)) { return(MondValue.Undefined); } if (result == null) { return(MondValue.Null); } var mondType = TypeConverter.ToMondType(result.GetType()); return(TypeConverter.MarshalToMond(result, mondType, state, options)); };
public static MondInstanceFunction CreateInstanceMethodShim( Type type, string name, MondBindingOptions options, bool isMetamethod = false) => delegate(MondState state, MondValue instance, MondValue[] args) { // Remove the object instance from the argument list. // This is primarily to prevent argument mismatch exceptions // when the Mond runtime tries to dispatch a metamethod. if ((args != null) && (args.Length >= 1) && (args[0] == instance) && (name.StartsWith("__") || isMetamethod)) { args = args.Skip(1).ToArray(); } var target = BindingUtils.GetTarget <MethodInfo>( type, name, args, BindingFlags.Public | BindingFlags.Instance, options); var values = TypeConverter.MarshalToClr(args, target.Types, state, options); var result = target.Method.Invoke(instance.UserData, values); if (target.Method.ReturnType == typeof(void)) { return(MondValue.Undefined); } if (result == null) { return(MondValue.Null); } var mondType = TypeConverter.ToMondType(result.GetType()); return(TypeConverter.MarshalToMond(result, mondType, state, options)); };
public static MondFunction CreateStaticOverloadGroupShim( IEnumerable <MethodInfo> methods, MondBindingOptions options) => delegate(MondState state, MondValue[] args) { var matcher = BindingUtils.CreateTargetMatcher <MethodInfo>(args, null, options); var matched = methods.Select(matcher).Where(m => m.Matched); var reflectedMembers = matched as ReflectedMember <MethodInfo>[] ?? matched.ToArray(); if (reflectedMembers.Length > 1) { throw new AmbiguousMatchException( "More than one delegate in the invokation list matches the argument list"); } if (reflectedMembers.Length == 0) { throw new MissingMethodException( "No delegate in the invokation list matches the argument list"); } var target = reflectedMembers[0]; var values = TypeConverter.MarshalToClr(args, target.Types, state, options); var result = target.Method.Invoke(null, values); if (target.Method.ReturnType == typeof(void)) { return(MondValue.Undefined); } if (result == null) { return(MondValue.Null); } var mondType = TypeConverter.ToMondType(result.GetType()); return(TypeConverter.MarshalToMond(result, mondType, state, options)); };