internal Object InvokeMember()

in src/Shared/Compat/TypeExtensions.cs [50:510]


            internal Object InvokeMember(
                String name, BindingFlags bindingFlags, Object target,
                Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
            {
                if (IsGenericParameter)
                    throw new InvalidOperationException("Arg_GenericParameter");
                Contract.EndContractBlock();

                #region Preconditions
                //if ((bindingFlags & InvocationMask) == 0)
                //    // "Must specify binding flags describing the invoke operation required."
                //    throw new ArgumentException("Arg_NoAccessSpec", "bindingFlags");

                // Provide a default binding mask if none is provided 
                if ((bindingFlags & MemberBindingMask) == 0)
                {
                    bindingFlags |= BindingFlags.Instance | BindingFlags.Public;

                    //if ((bindingFlags & BindingFlags.CreateInstance) == 0)
                    bindingFlags |= BindingFlags.Static;
                }

                // There must not be more named parameters than provided arguments
                if (namedParams != null)
                {
                    if (providedArgs != null)
                    {
                        if (namedParams.Length > providedArgs.Length)
                            // "Named parameter array can not be bigger than argument array."
                            throw new ArgumentException("Arg_NamedParamTooBig", "namedParams");
                    }
                    else
                    {
                        if (namedParams.Length != 0)
                            // "Named parameter array can not be bigger than argument array."
                            throw new ArgumentException("Arg_NamedParamTooBig", "namedParams");
                    }
                }
                #endregion

                #region COM Interop
#if FEATURE_COMINTEROP && FEATURE_USE_LCID
            if (target != null && target.GetType().IsCOMObject)
            {
                #region Preconditions
                if ((bindingFlags & ClassicBindingMask) == 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_COMAccess"), "bindingFlags");

                if ((bindingFlags & BindingFlags.GetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");

                if ((bindingFlags & BindingFlags.InvokeMethod) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");

                if ((bindingFlags & BindingFlags.SetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.SetProperty) != 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");

                if ((bindingFlags & BindingFlags.PutDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutDispProperty) != 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");

                if ((bindingFlags & BindingFlags.PutRefDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutRefDispProperty) != 0)
                    throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");
                #endregion

#if FEATURE_REMOTING
                if(!RemotingServices.IsTransparentProxy(target))
#endif
                {
                #region Non-TransparentProxy case
                    if (name == null)
                        throw new ArgumentNullException("name");

                    bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray;
                    
                    // pass LCID_ENGLISH_US if no explicit culture is specified to match the behavior of VB
                    int lcid = (culture == null ? 0x0409 : culture.LCID);

                    return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, lcid, namedParams);
                #endregion
                }
#if FEATURE_REMOTING
                else
                {
                #region TransparentProxy case
                    return ((MarshalByRefObject)target).InvokeMember(name, bindingFlags, binder, providedArgs, modifiers, culture, namedParams);
                #endregion
                }
#endif // FEATURE_REMOTING
            }
#endif // FEATURE_COMINTEROP && FEATURE_USE_LCID
                #endregion

                #region Check that any named paramters are not null
                if (namedParams != null && Array.IndexOf(namedParams, null) != -1)
                    // "Named parameter value must not be null."
                    throw new ArgumentException("Arg_NamedParamNull", "namedParams");
                #endregion

                int argCnt = (providedArgs != null) ? providedArgs.Length : 0;

                //#region Get a Binder
                //if (binder == null)
                //    binder = DefaultBinder;

                //bool bDefaultBinder = (binder == DefaultBinder);
                //#endregion

                //#region Delegate to Activator.CreateInstance
                //if ((bindingFlags & BindingFlags.CreateInstance) != 0)
                //{
                //    if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0)
                //        // "Can not specify both CreateInstance and another access type."
                //        throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"), "bindingFlags");

                //    return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture);
                //}
                //#endregion

                //// PutDispProperty and\or PutRefDispProperty ==> SetProperty.
                //if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0)
                //    bindingFlags |= BindingFlags.SetProperty;

                #region Name
                if (name == null)
                    throw new ArgumentNullException("name");

                if (name.Length == 0 || name.Equals(@"[DISPID=0]"))
                {
                    //name = GetDefaultMemberName();

                    if (name == null)
                    {
                        // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString
                        name = "ToString";
                    }
                }
                #endregion

                //#region GetField or SetField
                //bool IsGetField = (bindingFlags & BindingFlags.GetField) != 0;
                //bool IsSetField = (bindingFlags & BindingFlags.SetField) != 0;

                //if (IsGetField || IsSetField)
                //{
                //    #region Preconditions
                //    if (IsGetField)
                //    {
                //        if (IsSetField)
                //            // "Can not specify both Get and Set on a field."
                //            throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"), "bindingFlags");

                //        if ((bindingFlags & BindingFlags.SetProperty) != 0)
                //            // "Can not specify both GetField and SetProperty."
                //            throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"), "bindingFlags");
                //    }
                //    else
                //    {
                //        Contract.Assert(IsSetField);

                //        if (providedArgs == null)
                //            throw new ArgumentNullException("providedArgs");

                //        if ((bindingFlags & BindingFlags.GetProperty) != 0)
                //            // "Can not specify both SetField and GetProperty."
                //            throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"), "bindingFlags");

                //        if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
                //            // "Can not specify Set on a Field and Invoke on a method."
                //            throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"), "bindingFlags");
                //    }
                //    #endregion

                //    #region Lookup Field
                //    FieldInfo selFld = null;
                //    FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[];

                //    Contract.Assert(flds != null);

                //    if (flds.Length == 1)
                //    {
                //        selFld = flds[0];
                //    }
                //    else if (flds.Length > 0)
                //    {
                //        selFld = binder.BindToField(bindingFlags, flds, IsGetField ? Empty.Value : providedArgs[0], culture);
                //    }
                //    #endregion

                //    if (selFld != null)
                //    {
                //        #region Invocation on a field
                //        if (selFld.FieldType.IsArray || Object.ReferenceEquals(selFld.FieldType, typeof(System.Array)))
                //        {
                //            #region Invocation of an array Field
                //            int idxCnt;

                //            if ((bindingFlags & BindingFlags.GetField) != 0)
                //            {
                //                idxCnt = argCnt;
                //            }
                //            else
                //            {
                //                idxCnt = argCnt - 1;
                //            }

                //            if (idxCnt > 0)
                //            {
                //                // Verify that all of the index values are ints
                //                int[] idx = new int[idxCnt];
                //                for (int i = 0; i < idxCnt; i++)
                //                {
                //                    try
                //                    {
                //                        idx[i] = ((IConvertible)providedArgs[i]).ToInt32(null);
                //                    }
                //                    catch (InvalidCastException)
                //                    {
                //                        throw new ArgumentException(Environment.GetResourceString("Arg_IndexMustBeInt"));
                //                    }
                //                }

                //                // Set or get the value...
                //                Array a = (Array)selFld.GetValue(target);

                //                // Set or get the value in the array
                //                if ((bindingFlags & BindingFlags.GetField) != 0)
                //                {
                //                    return a.GetValue(idx);
                //                }
                //                else
                //                {
                //                    a.SetValue(providedArgs[idxCnt], idx);
                //                    return null;
                //                }
                //            }
                //            #endregion
                //        }

                //        if (IsGetField)
                //        {
                //            #region Get the field value
                //            if (argCnt != 0)
                //                throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"), "bindingFlags");

                //            return selFld.GetValue(target);
                //            #endregion
                //        }
                //        else
                //        {
                //            #region Set the field Value
                //            if (argCnt != 1)
                //                throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"), "bindingFlags");

                //            selFld.SetValue(target, providedArgs[0], bindingFlags, binder, culture);

                //            return null;
                //            #endregion
                //        }
                //        #endregion
                //    }

                //    if ((bindingFlags & BinderNonFieldGetSet) == 0)
                //        throw new MissingFieldException(FullName, name);
                //}
                //#endregion

                #region Caching Logic
                /*
                bool useCache = false;
                // Note that when we add something to the cache, we are careful to ensure
                // that the actual providedArgs matches the parameters of the method.  Otherwise,
                // some default argument processing has occurred.  We don't want anyone
                // else with the same (insufficient) number of actual arguments to get a
                // cache hit because then they would bypass the default argument processing
                // and the invocation would fail.
                if (bDefaultBinder && namedParams == null && argCnt < 6)
                    useCache = true;
                if (useCache)
                {
                    MethodBase invokeMethod = GetMethodFromCache (name, bindingFlags, argCnt, providedArgs);
                    if (invokeMethod != null)
                        return ((MethodInfo) invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
                }
                */
                #endregion

                //#region Property PreConditions
                //// @Legacy - This is RTM behavior
                //bool isGetProperty = (bindingFlags & BindingFlags.GetProperty) != 0;
                //bool isSetProperty = (bindingFlags & BindingFlags.SetProperty) != 0;

                //if (isGetProperty || isSetProperty)
                //{
                //    #region Preconditions
                //    if (isGetProperty)
                //    {
                //        Contract.Assert(!IsSetField);

                //        if (isSetProperty)
                //            throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");
                //    }
                //    else
                //    {
                //        Contract.Assert(isSetProperty);

                //        Contract.Assert(!IsGetField);

                //        if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
                //            throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");
                //    }
                //    #endregion
                //}
                //#endregion

                MethodInfo[] finalists = null;
                MethodInfo finalist = null;

                #region BindingFlags.InvokeMethod
                //if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
                {
                    #region Lookup Methods
                    //MethodInfo[] semiFinalists = GetMember(name, MemberTypes.Method, bindingFlags) as MethodInfo[];
                    MethodInfo[] semiFinalists = TargetType.GetMethods(bindingFlags).Where(mi => mi.Name == name).ToArray();
                    List<MethodInfo> results = null;

                    for (int i = 0; i < semiFinalists.Length; i++)
                    {
                        MethodInfo semiFinalist = semiFinalists[i];
                        Contract.Assert(semiFinalist != null);

                        if (!FilterApplyMethodBase(semiFinalist, bindingFlags, bindingFlags, CallingConventions.Any, new Type[argCnt]))
                            continue;

                        if (finalist == null)
                        {
                            finalist = semiFinalist;
                        }
                        else
                        {
                            if (results == null)
                            {
                                results = new List<MethodInfo>(semiFinalists.Length);
                                results.Add(finalist);
                            }

                            results.Add(semiFinalist);
                        }
                    }

                    if (results != null)
                    {
                        Contract.Assert(results.Count > 1);
                        finalists = new MethodInfo[results.Count];
                        results.CopyTo(finalists);
                    }
                    #endregion
                }
                #endregion

                Contract.Assert(finalists == null || finalist != null);

                //#region BindingFlags.GetProperty or BindingFlags.SetProperty
                //if (finalist == null && isGetProperty || isSetProperty)
                //{
                //    #region Lookup Property
                //    PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[];
                //    List<MethodInfo> results = null;

                //    for (int i = 0; i < semiFinalists.Length; i++)
                //    {
                //        MethodInfo semiFinalist = null;

                //        if (isSetProperty)
                //        {
                //            semiFinalist = semiFinalists[i].GetSetMethod(true);
                //        }
                //        else
                //        {
                //            semiFinalist = semiFinalists[i].GetGetMethod(true);
                //        }

                //        if (semiFinalist == null)
                //            continue;

                //        if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
                //            continue;

                //        if (finalist == null)
                //        {
                //            finalist = semiFinalist;
                //        }
                //        else
                //        {
                //            if (results == null)
                //            {
                //                results = new List<MethodInfo>(semiFinalists.Length);
                //                results.Add(finalist);
                //            }

                //            results.Add(semiFinalist);
                //        }
                //    }

                //    if (results != null)
                //    {
                //        Contract.Assert(results.Count > 1);
                //        finalists = new MethodInfo[results.Count];
                //        results.CopyTo(finalists);
                //    }
                //    #endregion
                //}
                //#endregion

                if (finalist != null)
                {
                    #region Invoke
                    if (finalists == null &&
                        argCnt == 0 &&
                        finalist.GetParameters().Length == 0 
                        //&& (bindingFlags & BindingFlags.OptionalParamBinding) == 0
                        )
                    {
                        //if (useCache && argCnt == props[0].GetParameters().Length)
                        //    AddMethodToCache(name, bindingFlags, argCnt, providedArgs, props[0]);

                        //return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture);
                        return finalist.Invoke(target, providedArgs);
                    }

                    if (finalists == null)
                        finalists = new MethodInfo[] { finalist };

                    if (providedArgs == null)
                        providedArgs = Array.Empty<object>();

                    Object state = null;


                    MethodBase invokeMethod = null;

                    try { invokeMethod = DefaultBinder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); }
                    catch (MissingMethodException) { }

                    if (invokeMethod == null)
                        throw new MissingMethodException(TargetType.FullName + "." + name);

                    //if (useCache && argCnt == invokeMethod.GetParameters().Length)
                    //    AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod);

                    //Object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
                    Object result = ((MethodInfo)invokeMethod).Invoke(target, providedArgs);

                    if (state != null)
                        DefaultBinder.ReorderArgumentArray(ref providedArgs, state);

                    return result;
                    #endregion
                }

                throw new MissingMethodException(TargetType.FullName + "." + name);
            }