public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) { const string bindingflags_arg = "bindingFlags"; if ((invokeAttr & BindingFlags.CreateInstance) != 0) { if ((invokeAttr & (BindingFlags.GetField | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.SetProperty)) != 0) throw new ArgumentException (bindingflags_arg); } else if (name == null) throw new ArgumentNullException ("name"); if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0) throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg); if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0) throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg); if ((invokeAttr & BindingFlags.InvokeMethod) != 0) { if ((invokeAttr & BindingFlags.SetField) != 0) throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg); if ((invokeAttr & BindingFlags.SetProperty) != 0) throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg); } if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length)) throw new ArgumentException ("namedParameters cannot be more than named arguments in number"); if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0) throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg); /* set some defaults if none are provided :-( */ if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0) invokeAttr |= BindingFlags.Public; if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0) invokeAttr |= BindingFlags.Static|BindingFlags.Instance; if (binder == null) binder = Binder.DefaultBinder; if ((invokeAttr & BindingFlags.CreateInstance) != 0) { /* the name is ignored */ invokeAttr |= BindingFlags.DeclaredOnly; ConstructorInfo[] ctors = GetConstructors (invokeAttr); object state = null; MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state); if (ctor == null) { if (this.IsValueType && args == null) return Activator.CreateInstanceInternal (this); throw new MissingMethodException ("Constructor on type '" + FullName + "' not found."); } object result = ctor.Invoke (target, invokeAttr, binder, args, culture); binder.ReorderArgumentArray (ref args, state); return result; } if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) { DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute)); name = attr.MemberName; } bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0; string throwMissingMethodDescription = null; bool throwMissingFieldException = false; if ((invokeAttr & BindingFlags.InvokeMethod) != 0) { MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this); object state = null; if (args == null) args = EmptyArray<object>.Value; MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state); if (m == null) { if (methods.Length > 0) throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter."; else throwMissingMethodDescription = "Cannot find method " + name + "."; } else { ParameterInfo[] parameters = m.GetParameters(); for (int i = 0; i < parameters.Length; ++i) { if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault) throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters"); } object result = m.Invoke (target, invokeAttr, binder, args, culture); binder.ReorderArgumentArray (ref args, state); return result; } } if ((invokeAttr & BindingFlags.GetField) != 0) { FieldInfo f = GetField (name, invokeAttr); if (f != null) { return f.GetValue (target); } else if ((invokeAttr & BindingFlags.GetProperty) == 0) { throwMissingFieldException = true; } /* try GetProperty */ } else if ((invokeAttr & BindingFlags.SetField) != 0) { FieldInfo f = GetField (name, invokeAttr); if (f != null) { if (args == null) throw new ArgumentNullException ("providedArgs"); if ((args == null) || args.Length != 1) throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg); f.SetValue (target, args [0]); return null; } else if ((invokeAttr & BindingFlags.SetProperty) == 0) { throwMissingFieldException = true; } /* try SetProperty */ } if ((invokeAttr & BindingFlags.GetProperty) != 0) { PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this); object state = null; int i, count = 0; for (i = 0; i < properties.Length; ++i) { if ((properties [i].GetGetMethod (true) != null)) count++; } MethodBase[] smethods = new MethodBase [count]; count = 0; for (i = 0; i < properties.Length; ++i) { MethodBase mb = properties [i].GetGetMethod (true); if (mb != null) smethods [count++] = mb; } MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state); if (m == null) { throwMissingFieldException = true; } else { object result = m.Invoke (target, invokeAttr, binder, args, culture); binder.ReorderArgumentArray (ref args, state); return result; } } else if ((invokeAttr & BindingFlags.SetProperty) != 0) { PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this); object state = null; int i, count = 0; for (i = 0; i < properties.Length; ++i) { if (properties [i].GetSetMethod (true) != null) count++; } MethodBase[] smethods = new MethodBase [count]; count = 0; for (i = 0; i < properties.Length; ++i) { MethodBase mb = properties [i].GetSetMethod (true); if (mb != null) smethods [count++] = mb; } MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state); if (m == null) { throwMissingFieldException = true; } else { object result = m.Invoke (target, invokeAttr, binder, args, culture); binder.ReorderArgumentArray (ref args, state); return result; } } if (throwMissingMethodDescription != null) throw new MissingMethodException(throwMissingMethodDescription); if (throwMissingFieldException) throw new MissingFieldException("Cannot find variable " + name + "."); return null; }
public override void ReorderArgumentArray(ref object[] args, object state) { _binder.ReorderArgumentArray(ref args, state); }
internal Object CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) { Object server = null; try { // Store the activation attributes in thread local storage. // These attributes are later picked up by specialized // activation services like remote activation services to // influence the activation. if(null != activationAttributes) { ActivationServices.ActivationAttributes = activationAttributes; } if (args == null) args = new Object[0]; int argCnt = args.Length; // Without a binder we need to do use the default binder... if (binder == null) binder = DefaultBinder; // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors // so a call to GetMemberCons would fail if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 && (IsGenericCOMObjectImpl() || IsSubclassOf(RuntimeType.valueType))) { server = CreateInstanceImpl(((bindingAttr & BindingFlags.NonPublic) != 0) ? false : true); } else { bool isDelegate; MethodBase[] cons = GetMemberCons(bindingAttr, CallingConventions.Any, null, argCnt, false, /*binder == DefaultBinder, */ out isDelegate); if (cons == null) throw new MissingMethodException(String.Format(Environment.GetResourceString("MissingConstructor_Name"), FullName)); // It would be strange to have an argCnt of 0 and more than // one constructor. if (argCnt == 0 && cons.Length == 1 && (bindingAttr & BindingFlags.OptionalParamBinding) == 0) server = Activator.CreateInstance(this, true); else { // MethodBase invokeMethod = binder.BindToMethod(cons,args,null,null,culture); MethodBase invokeMethod; Object state; invokeMethod = binder.BindToMethod(bindingAttr,cons,ref args,null,culture,null, out state); if (invokeMethod == null) throw new MissingMethodException(String.Format(Environment.GetResourceString("MissingConstructor_Name"), FullName)); // If we're creating a delegate, we're about to call a // constructor taking an integer to represent a target // method. Since this is very difficult (and expensive) // to verify, we're just going to demand UnmanagedCode // permission before allowing this. Partially trusted // clients can instead use Delegate.CreateDelegate, // which allows specification of the target method via // name or MethodInfo. if (isDelegate) new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); server = ((ConstructorInfo) invokeMethod).Invoke(bindingAttr,binder,args,culture); if (state != null) binder.ReorderArgumentArray(ref args, state); } } } finally { // Reset the TLS to null if(null != activationAttributes) { ActivationServices.ActivationAttributes = null; } } return server; }
public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) { if (type == null) throw new ArgumentNullException(nameof(type)); // If they didn't specify a lookup, then we will provide the default lookup. const BindingFlags LookupMask = (BindingFlags)0x000000FF; if ((bindingAttr & LookupMask) == 0) bindingAttr |= BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance; if (activationAttributes != null && activationAttributes.Length > 0) throw new NotSupportedException(SR.NotSupported_ActivAttr); type = type.UnderlyingSystemType; CreateInstanceCheckType(type); if (args == null) args = Array.Empty<object>(); int numArgs = args.Length; // This short-circuit depends on the fact that the toolchain prohibits valuetypes with nullary constructors. Unfortunately, we can't check for the presence of nullary // constructors without risking a MissingMetadataException, and we can't regress the prior N behavior that allowed CreateInstance on valuetypes to work regardless of metadata. if (numArgs == 0 && type.IsValueType) return RuntimeAugments.NewObject(type.TypeHandle); Type[] argTypes = new Type[numArgs]; for (int i = 0; i < numArgs; i++) { argTypes[i] = args[i]?.GetType(); } ConstructorInfo[] candidates = type.GetConstructors(bindingAttr); ListBuilder<MethodBase> matches = new ListBuilder<MethodBase>(candidates.Length); for (int i = 0; i < candidates.Length; i++) { if (candidates[i].QualifiesBasedOnParameterCount(bindingAttr, CallingConventions.Any, argTypes)) matches.Add(candidates[i]); } if (matches.Count == 0) throw new MissingMethodException(SR.Arg_NoDefCTor); if (binder == null) binder = Type.DefaultBinder; object state = null; MethodBase invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out state); if (invokeMethod.GetParametersNoCopy().Length == 0) { if (args.Length != 0) { Debug.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs); throw new NotSupportedException(SR.NotSupported_CallToVarArg); } // Desktop compat: CoreClr invokes a "fast-path" here (call Activator.CreateInstance(type, true)) that also // bypasses the binder.ReorderArgumentArray() call. That "fast-path" isn't a fast-path for us so we won't do that // but we'll still null out the "state" variable to bypass the Reorder call. // // The only time this matters at all is if (1) a third party binder is being used and (2) it actually reordered the array // which it shouldn't have done because (a) we didn't request it to bind arguments by name, and (b) it's kinda hard to // reorder a zero-length args array. But who knows what a third party binder will do if we make a call to it that we didn't // used to do, so we'll preserve the CoreClr order of calls just to be safe. state = null; } object result = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); if (state != null) binder.ReorderArgumentArray(ref args, state); return result; }
public override Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) { // Did we specify an access type? //Console.WriteLine("InvokeAttr:" + (int) invokeAttr); if ((invokeAttr & (BindingFlags) BinderAccessMask) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),"invokeAttr"); // Did we specify an CreateInstance and another access type? if ((invokeAttr & BindingFlags.CreateInstance) != 0 && (invokeAttr & (BindingFlags) BinderNonCreateInstance) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),"invokeAttr"); // If they didn't specify a lookup, then we will provide the default lookup. if ((invokeAttr & (BindingFlags) LookupMask) == 0) { invokeAttr |= BindingFlags.Instance | BindingFlags.Public; if ((invokeAttr & BindingFlags.CreateInstance) == 0) invokeAttr |= BindingFlags.Static; } // if the number of names is bigger than the number of args we have a problem if (namedParameters != null && ((args == null && namedParameters.Length != 0) || (args != null && namedParameters.Length > args.Length))) throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"),"namedParameters"); if (namedParameters != null) for (int i=0;i<namedParameters.Length;i++) if (namedParameters[i] == null) throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),"namedParameters"); // The number of arguments to the method. We will only match // arguments that match directly. int argCnt = (args != null) ? args.Length : 0; // Without a binder we need to do use the default binder... if (binder == null) binder = DefaultBinder; bool bDefaultBinder = (binder == DefaultBinder); if ((invokeAttr & BindingFlags.CreateInstance) != 0) return Activator.CreateInstance(this,invokeAttr,binder,args,culture); // When calling on a managed component, we consider both PutDispProperty and // PutRefDispProperty to be equivalent to SetProperty. if ((invokeAttr & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0) invokeAttr |= BindingFlags.SetProperty; // For fields, methods and properties the name must be specified. if (name == null) throw new ArgumentNullException("name"); MethodInfo[] props=null; MethodInfo[] meths=null; // We will narrow down the search to a field first... FieldInfo selFld=null; // if we are looking for the default member, find it... 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"; } } // Fields if ((invokeAttr & BindingFlags.GetField) != 0 || (invokeAttr & BindingFlags.SetField) != 0) { FieldInfo[] flds=null; // validate the set/get stuff if (((invokeAttr & (BindingFlags) BinderGetSetField) ^ (BindingFlags) BinderGetSetField) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),"invokeAttr"); if (((invokeAttr & (BindingFlags) BinderSetInvokeField) ^ (BindingFlags)BinderSetInvokeField) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),"invokeAttr"); bool fieldGet = ((invokeAttr & BindingFlags.GetField) != 0); if (fieldGet) { if ((invokeAttr & BindingFlags.SetProperty) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"invokeAttr"); } else { if ((invokeAttr & BindingFlags.GetProperty) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"invokeAttr"); } flds = GetMemberField(name,invokeAttr, false); // We are only doing a field/set get if (flds != null) { if (flds.Length != 1) { Object o; if (fieldGet) o = Empty.Value; else { if (args == null) throw new ArgumentNullException("args"); o = args[0]; } selFld = binder.BindToField(invokeAttr,flds,o,culture); } else { selFld = flds[0]; } } // If we are only set/get field we leave here with errors... if ((invokeAttr & (BindingFlags) BinderNonFieldGetSet) == 0) { if (flds == null) throw new MissingFieldException(FullName, name); if (flds.Length == 1) selFld = flds[0]; else if (selFld == null) throw new MissingFieldException(FullName, name); } // If we can continue we leave if we found a field. Fields // now have the highest priority. if (selFld != null) { //Console.WriteLine(selFld.FieldType.Name); //Console.WriteLine("argCnt:" + argCnt); // For arrays we are going to see if they are trying to access the array if (selFld.FieldType.IsArray || selFld.FieldType == typeof(System.Array)) { int idxCnt; if ((invokeAttr & 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)args[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 ((invokeAttr & BindingFlags.GetField) != 0) { return a.GetValue(idx); } else { a.SetValue(args[idxCnt],idx); return null; } } } else { // This is not an array so we validate that the arg count is correct. if ((invokeAttr & BindingFlags.GetField) != 0 && argCnt != 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),"invokeAttr"); if ((invokeAttr & BindingFlags.SetField) != 0 && argCnt != 1) throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),"invokeAttr"); } // Set the field... if (fieldGet) return selFld.GetValue(target); else { selFld.SetValue(target,args[0],invokeAttr,binder,culture); return null; } } } // Properties MethodBase invokeMethod; bool useCache = false; // Note that when we add something to the cache, we are careful to ensure // that the actual args 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 && namedParameters == null && argCnt < 6) useCache = true; if (useCache) { invokeMethod = nGetMethodFromCache (name, invokeAttr, argCnt, args); if (invokeMethod != null) return ((MethodInfo) invokeMethod).Invoke(target,invokeAttr,binder,args,culture); } if ((invokeAttr & BindingFlags.GetProperty) != 0 || (invokeAttr & BindingFlags.SetProperty) != 0) { if (((invokeAttr & (BindingFlags) BinderGetSetProperty) ^ (BindingFlags) BinderGetSetProperty) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"),"invokeAttr"); if (((invokeAttr & (BindingFlags) BinderSetInvokeProperty) ^ (BindingFlags) BinderSetInvokeProperty) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"),"invokeAttr"); bool propGet = ((invokeAttr & BindingFlags.GetProperty) != 0); if (propGet) { if ((invokeAttr & BindingFlags.SetField) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"invokeAttr"); } else { if ((invokeAttr & BindingFlags.GetField) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"invokeAttr"); } props = GetMemberProperties(name,invokeAttr,argCnt, false); } if ((invokeAttr & BindingFlags.InvokeMethod) != 0) { meths = GetMemberMethod(name, invokeAttr, CallingConventions.Any, null, argCnt, false); } if (meths == null && props == null) throw new MissingMethodException(FullName, name); // if either props or meths is null then we simply work with // the other one. (One must be non-null because of the if statement above) if (props == null) { if (argCnt == 0 && meths[0].GetParameters().Length == 0 && (invokeAttr & BindingFlags.OptionalParamBinding) == 0) { if (useCache && argCnt == meths[0].GetParameters().Length) nAddMethodToCache(name,invokeAttr,argCnt,args,meths[0]); return meths[0].Invoke(target,invokeAttr,binder,args,culture); } else { if (args == null) args = new Object[0]; Object state = null; invokeMethod = binder.BindToMethod(invokeAttr,meths,ref args,modifiers,culture,namedParameters, out state); if (invokeMethod == null) throw new MissingMethodException(FullName, name); if (useCache && argCnt == invokeMethod.GetParameters().Length) nAddMethodToCache(name,invokeAttr,argCnt,args,invokeMethod); Object result = ((MethodInfo) invokeMethod).Invoke(target,invokeAttr,binder,args,culture); if (state != null) binder.ReorderArgumentArray(ref args, state); return result; } } if (meths == null) { if (argCnt == 0 && props[0].GetParameters().Length == 0 && (invokeAttr & BindingFlags.OptionalParamBinding) == 0) { if (useCache && argCnt == props[0].GetParameters().Length) nAddMethodToCache(name,invokeAttr,argCnt,args,props[0]); return props[0].Invoke(target,invokeAttr,binder,args,culture); } else { if (args == null) args = new Object[0]; Object state = null; invokeMethod = binder.BindToMethod(invokeAttr,props,ref args,modifiers,culture,namedParameters, out state); if (invokeMethod == null) throw new MissingMethodException(FullName, name); if (useCache && argCnt == invokeMethod.GetParameters().Length) nAddMethodToCache(name,invokeAttr,argCnt,args,invokeMethod); Object result = ((MethodInfo) invokeMethod).Invoke(target,invokeAttr,binder,args,culture); if (state != null) binder.ReorderArgumentArray(ref args, state); return result; } } // Now we have both methods and properties... MethodInfo[] p = new MethodInfo[props.Length + meths.Length]; Array.Copy(meths,p,meths.Length); Array.Copy(props,0,p,meths.Length,props.Length); if (args == null) args = new Object[0]; Object binderState = null; invokeMethod = binder.BindToMethod(invokeAttr,p,ref args,modifiers,culture,namedParameters, out binderState); if (invokeMethod == null) throw new MissingMethodException(FullName, name); if (useCache && argCnt == invokeMethod.GetParameters().Length) nAddMethodToCache(name,invokeAttr,argCnt,args,invokeMethod); Object res = ((MethodInfo) invokeMethod).Invoke(target,invokeAttr,binder,args,culture); if (binderState != null) { binder.ReorderArgumentArray(ref args, binderState); } return res; }