public DelegateGroup MakeGenericMethod(params Type[] types) { List <MethodBase> newmethods = new List <MethodBase>(); foreach (MethodBase method in methods) { MethodInfo info = method as MethodInfo; if (info != null && info.IsGenericMethodDefinition) { try { MethodInfo rmethod = info.MakeGenericMethod(types); newmethods.Add(rmethod); } catch (ArgumentException) { } } } DelegateGroup result = new DelegateGroup(); result.methods = newmethods.ToArray(); result.target = target; return(result); }
/// <summary> /// Get an element from an array or collection, or invoke a delegate. /// </summary> /// <param name="target">An array, collection, delegate, or method group.</param> /// <param name="args">Indices for the collection or arguments for the delegate. May be null.</param> /// <returns>The collection element or return value of the delegate. If args == null, the target itself.</returns> public static object GetValue(object target, params object[] args) { if (args == null) { return(target); } Delegate d = target as Delegate; if (d != null) { return(InvokeMember(d.GetType(), "Invoke", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, d, args)); } DelegateGroup dg = target as DelegateGroup; if (dg != null) { return(dg.DynamicInvoke(args)); } if (args.Length == 0) { return(target); } Array array = target as Array; if (array != null) { int[] index = Array.ConvertAll <object, int>(args, delegate(object o) { return(Convert.ToInt32(o)); }); return(array.GetValue(index)); } if (target == null) { return(target); } //throw new ArgumentNullException("The field/property value is null"); // collection return(InvokeMember(target.GetType(), "Item", BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty, target, args)); }
/// <summary> /// Invoke the member which best matches the argument types. /// </summary> /// <param name="type">The type defining the member.</param> /// <param name="memberName">The name of a field, property, event, instance method, or static method.</param> /// <param name="flags"></param> /// <param name="target">The object whose member to invoke. Ignored for a static field or property. /// If target is non-null, then it is provided as the first argument to a static method.</param> /// <param name="args">Can be empty or null. Empty means a function call with no arguments. /// null means get the member itself.</param> /// <returns>The result of the invocation. For SetField/SetProperty the result is null.</returns> /// <exception cref="MissingMemberException"></exception> /// <exception cref="ArgumentException"></exception> /// <remarks><para> /// This routine is patterned after Type.InvokeMember. /// flags must specify Instance, Static, or both. /// </para><para> /// If flags contains CreateInstance, then name is ignored and a constructor is invoked. /// </para><para> /// If memberName names a field/property and flags contains SetField/SetProperty, /// then the field/property's value is changed to args[args.Length-1]. /// If args.Length > 1, the field/property is indexed by args[0:(args.Length-2)]. /// </para><para> /// If memberName names a field/property and flags contains GetField/GetProperty, /// then the field/property's value is returned. /// If args != null and the field/property is a delegate, then it is invoked with args. /// Otherwise if args != null, the field/property is indexed by args. /// </para><para> /// If memberName names an event and flags contains GetField, /// then the event's EventInfo is returned. /// If args != null, then the event is raised with args. /// </para><para> /// If memberName names a method and flags contains InvokeMethod, /// then it is invoked with args. A static method is invoked with target and args. /// If args == null, then the result is a DelegateGroup containing all overloads of the method. /// </para><para> /// Other flag values are implemented as in Type.InvokeMember. /// In each case, overloading is resolved by matching the argument types, possibly with conversions. /// </para><para> /// If a matching member is not found, the interfaces of the type are also searched. /// As a last resort, if the memberName is op_Equality or op_Inequality, then a default implementation /// is provided (as in C#). /// </para></remarks> public static object InvokeMember(Type type, string memberName, BindingFlags flags, object target, params object[] args) { if ((flags & BindingFlags.GetField) == BindingFlags.GetField) { FieldInfo field = type.GetField(memberName, flags); if (field != null) { object value = field.GetValue(target); value = GetValue(value, args); return(value); } EventInfo evnt = type.GetEvent(memberName, flags); if (evnt != null) { if (args == null) { return(evnt); } //MethodInfo raiser = evnt.GetRaiseMethod(); //return raiser.Invoke(target, args); //return type.InvokeMember(memberName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.InvokeMethod, null, target, args); // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=130529&SiteID=1 return(new NotSupportedException("Raising events is not supported by Reflection")); } } if ((flags & BindingFlags.SetField) == BindingFlags.SetField) { FieldInfo field = type.GetField(memberName, flags); if (field != null) { if (args == null || args.Length == 0) { throw new ArgumentException("No value was provided to set"); } if (args.Length == 1) { object value = args[0]; Conversion conv; if (!Conversion.TryGetConversion(value == null ? null : value.GetType(), field.FieldType, out conv)) { throw new ArgumentException("The value (" + args[0] + ") does not match the field type (" + field.FieldType.Name + ")"); } if (conv.Converter != null) { value = conv.Converter(value); } field.SetValue(target, value); } else { SetValue(field.GetValue(target), args); } return(null); } } if ((flags & BindingFlags.GetProperty) == BindingFlags.GetProperty) { PropertyInfo[] props = type.GetProperties(flags); props = Array.FindAll <PropertyInfo>(props, delegate(PropertyInfo p) { return(p.Name == memberName); }); if (props.Length > 0) { PropertyInfo prop = props[0]; int rank = prop.GetIndexParameters().Length; if (rank > 0) { //if(rank != args.Length) throw new ArgumentException("Not enough arguments for indexed property"); // indexed property memberName = "get_" + memberName; //MethodInfo method = type.GetMethod(memberName); return(InvokeMember(type, memberName, flags | BindingFlags.InvokeMethod, target, args)); } // not indexed property object value = prop.GetValue(target, null); value = GetValue(value, args); return(value); } } if ((flags & BindingFlags.SetProperty) == BindingFlags.SetProperty) { PropertyInfo[] props = type.GetProperties(flags); props = Array.FindAll <PropertyInfo>(props, delegate(PropertyInfo p) { return(p.Name == memberName); }); if (props.Length > 0) { if (args == null || args.Length == 0) { throw new ArgumentException("No value was provided to set"); } //PropertyInfo prop = type.GetProperty(memberName, flags); PropertyInfo prop = props[0]; int rank = prop.GetIndexParameters().Length; if (rank > 0 || args.Length == 1) { // indexed property memberName = "set_" + memberName; //MethodInfo method = type.GetMethod(memberName); return(InvokeMember(type, memberName, flags | BindingFlags.InvokeMethod, target, args)); } // not indexed property SetValue(prop.GetValue(target, null), args); return(null); } } if ((flags & BindingFlags.InvokeMethod) == BindingFlags.InvokeMethod) { // must explicitly search through BaseTypes because static methods are not inherited Type baseType = type; while (baseType != null) { MethodInfo[] methods = baseType.GetMethods(flags); methods = Array.FindAll(methods, delegate(MethodInfo method) { return(method.Name == memberName); }); if (methods.Length > 0) { if (args == null) { // even if there is only one method, we can't create a delegate because we don't know the // desired delegate type. DelegateGroup dg = new DelegateGroup(); dg.target = target; dg.methods = methods; return(dg); } return(Invoke(methods, target, args)); } baseType = baseType.BaseType; } } // search through interfaces Type[] faces = type.GetInterfaces(); foreach (Type face in faces) { try { return(InvokeMember(face, memberName, flags, target, args)); } catch (MissingMemberException) { } } // default operator implementations if ((flags & BindingFlags.InvokeMethod) == BindingFlags.InvokeMethod && (flags & BindingFlags.Static) == BindingFlags.Static) { if (memberName == "op_Equality" || memberName == "op_Inequality" || memberName == "op_GreaterThan" || memberName == "op_LessThan" || memberName == "op_GreaterThanOrEqual" || memberName == "op_LessThanOrEqual" || memberName == "op_Subtraction" || memberName == "op_Addition" || memberName == "op_BooleanOr" || memberName == "op_BooleanAnd" || memberName == "op_BooleanNot" || memberName == "op_UnaryNegation") { return(InvokeMember(typeof(Invoker), memberName, BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, target, args)); } } throw new MissingMemberException(type.ToString() + " has no member named " + memberName + " under the binding flags " + flags); }