Calling methods with optional parameters through reflection

I ran into another problem using C # 4.0 with extra parameters.

How do I call a function (or rather a constructor, I have a ConstructorInfo object) for which I know that it does not require any parameters?

Here is the code I'm using now:

 type.GetParameterlessConstructor() .Invoke(BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod | BindingFlags.CreateInstance, null, new object[0], CultureInfo.InvariantCulture); 

(I just tried with different BindingFlags ).

GetParameterlessConstructor is a special extension method that I wrote for Type .

+49
reflection c # invoke default-value
Mar 11
source share
5 answers

According to MSDN , in order to use the default parameter, you must pass Type.Missing .

If your constructor has three optional arguments, then instead of passing an empty array of objects, you should pass an array of three elements, where each value of the Type.Missing element, for example.

 type.GetParameterlessConstructor() .Invoke(BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod | BindingFlags.CreateInstance, null, new object[] { Type.Missing, Type.Missing, Type.Missing }, CultureInfo.InvariantCulture); 
+102
Mar 28 '12 at 21:52
source share
— -

Additional parameters are indicated by the usual attribute and are processed by the compiler.
They do not affect (except the metadata flag) IL and are not directly supported by reflection (except for the IsOptional and IsOptional properties).

If you want to use optional parameters with reflection, you need to manually pass your default values.

+22
Mar 11
source share

I will just add the code ... because. I do not agree with this code, but it is pretty straight forward. Hope this helps someone who stumbles about it. It is tested, although probably not as good as you would like in a production environment:

The methodName method call on the obj object with args arguments:

  public Tuple<bool, object> Evaluate(IScopeContext c, object obj, string methodName, object[] args) { // Get the type of the object var t = obj.GetType(); var argListTypes = args.Select(a => a.GetType()).ToArray(); var funcs = (from m in t.GetMethods() where m.Name == methodName where m.ArgumentListMatches(argListTypes) select m).ToArray(); if (funcs.Length != 1) return new Tuple<bool, object>(false, null); // And invoke the method and see what we can get back. // Optional arguments means we have to fill things in. var method = funcs[0]; object[] allArgs = args; if (method.GetParameters().Length != args.Length) { var defaultArgs = method.GetParameters().Skip(args.Length) .Select(a => a.HasDefaultValue ? a.DefaultValue : null); allArgs = args.Concat(defaultArgs).ToArray(); } var r = funcs[0].Invoke(obj, allArgs); return new Tuple<bool, object>(true, r); } 

And the ArgumentListMatches function below, which basically replaces the logic that is probably found in GetMethod:

  public static bool ArgumentListMatches(this MethodInfo m, Type[] args) { // If there are less arguments, then it just doesn't matter. var pInfo = m.GetParameters(); if (pInfo.Length < args.Length) return false; // Now, check compatibility of the first set of arguments. var commonArgs = args.Zip(pInfo, (margs, pinfo) => Tuple.Create(margs, pinfo.ParameterType)); if (commonArgs.Where(t => !t.Item1.IsAssignableFrom(t.Item2)).Any()) return false; // And make sure the last set of arguments are actually default! return pInfo.Skip(args.Length).All(p => p.IsOptional); } 

Lots of LINQ, and it has not been tested for performance!

In addition, it will not handle calls to a common function or method. This makes it significantly more ugly (as in GetMethod repeated calls).

+3
Mar 19 '15 at 22:55
source share

With the original ImpromptuInterface structure from version 4, you can use DLR in C # 4.0 to call constructors in a very late bound path , and it fully knows constructors with named / optional arguments, this is 4 times faster than Activator.CreateInstance(Type type, params object[] args) , and you do not need to reflect the default values.

 using ImpromptuInterface; using ImpromptuInterface.InvokeExt; 

...

 //if all optional and you don't want to call any Impromptu.InvokeConstructor(type) 

or

 //If you want to call one parameter and need to name it Impromptu.InvokeConstructor(type, CultureInfo.InvariantCulture.WithArgumentName("culture")) 
+1
Apr 16 '11 at 23:11
source share

All questions disappear as you see that your code is decompiled:

FROM#:

 public MyClass([Optional, DefaultParameterValue("")]string myOptArg) 

MSIL:

 .method public hidebysig specialname rtspecialname instance void .ctor([opt]string myOptArg) cil managed 

As you can see, the optional parameter is a real separate object that is decorated with certain attributes and must be respected accordingly when called through reflection, as described above.

+1
Apr 04 '16 at 8:00
source share



All Articles