Пример #1
0
        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);
        }
Пример #2
0
        /// <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));
        }
Пример #3
0
 /// <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);
 }