InvokeMember in c# with "reflected" parameters - c#

I want to call a method of a DLL via reflection (can't be sure that the other dll is loaded) but have problems with the parameters.
The method I want to call is
public void Add(DBTable table, String sField, DBValue value, SQLConditionType type)
in the MP-TVSeries project
What I tried is this:
// WindowPlugins.GUITVSeries
Assembly MPTVSeries = Assembly.Load("MP-TVSeries");
Type sqlConditionType = MPTVSeries.GetType("WindowPlugins.GUITVSeries.SQLCondition");
Type sqlConditionTypeEnumType = MPTVSeries.GetType("WindowPlugins.GUITVSeries.SQLConditionType");
Type dbEpisode = MPTVSeries.GetType("WindowPlugins.GUITVSeries.DBEpisode");
// SQLCondition sql = new SQLCondition();
object sql = Activator.CreateInstance(sqlConditionType);
// sql.Add(new DBEpisode(), DBEpisode.cFilename, filename, SQLConditionType.Equal);
sqlConditionType.InvokeMember("Add",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
null,
sql,
new object[] {
Activator.CreateInstance(dbEpisode),
dbEpisode.GetField("cFilename"),
filename,
sqlConditionTypeEnumType.GetField("Equal")
});
but this throws an exception with the message
The method "WindowPlugins.GUITVSeries.SQLCondition.Add"
could not be found.
My guess is that I am doing something wrong with the parameters, but as I am totally new to reflection I can't get my head around it.
Someone please help ;-)

You are going too fast. Get sqlConditionType.GetMethod() working first to get a MethodInfo so you can be sure this is not a method overload resolution problem. The arguments you pass are smelly, particularly filename and sqlConditionTypeEnumType.GetField("Equal").

Related

Use Compiled Lambda expression instead of Activator.CreateInstance to initialize SoapHttpClientProtocol object

I'm working with the code that dynamically instantiates SoapHttpClientProtocol object (proxy class) and uses this object to make a call to WS-Basic I Web Service. Here is the simplified version of my code:
public override object Call(Type callingObject,
string method, object[] methodParams, string URL)
{
MethodInfo requestMethod = callingObject.GetMethod(method);
//creates an instance of SoapHttpClientProtocol
object instance = Activator.CreateInstance(callingObject);
//sets the URL for the object that was just created
instance.GetType().InvokeMember("Url",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null,
instance,
new object[1] {URL});
return requestMethod.Invoke(instance, methodParams);
}
I've noticed that in some cases Activator.CreateInstance() call can take significant amount of time, so I'm trying to optimize the code by using a lambda expression:
public override object Call(Type callingObject,
string method, object[] methodParams, string URL)
{
MethodInfo requestMethod = callingObject.GetMethod(method);
//creates an instance of SoapHttpClientProtocol using compiled Lambda Expression
ConstructorInfo constructorInfo = callingObject.GetConstructor(new Type[0]);
object instance = Expression.Lambda(Expression.New(constructorInfo)).Compile();
//sets the URL for the object that was just created
instance.GetType().InvokeMember("Url",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null,
instance,
new object[1] {URL});
//calls the web service
return requestMethod.Invoke(instance, methodParams);
}
Unfortunately, this code does not create an object of the callingObject type (instead it returns a Func<T> delegate object) and therefore when it tries to set the Url in the next line it throws an exception:
System.MissingMethodException: Attempted to access a missing member.
Am I missing something in my code?
Thanks!
The Expression.Lambda(Expression.New(constructorInfo)).Compile() part returns a Func<T> delegate that wraps a constructor of Type stored in callingObject parameter. To actually call that constructor, you still need to invoke it:
Delegate delegateWithConstructor = Expression.Lambda(Expression.New(constructorInfo)).Compile();
object instance = delegateWithConstructor.DynamicInvoke();
However, what you are trying to do seems quite strange and fragile in the long run, since you are passing around method names as simple strings and parameters as objects, therefore losing all compile-time type checking. Why do you need to do it?
Using expression trees will cause your program to run slower unless You cache compiled expression.

reflection calling 2 methods

I'm trying to do something like this but with reflection:
var ss1= method1(param).method2();
I know how to invoke the first method but I don't know how to invoke the second one.
method 1 returns an object
method 2 is the GetAwaiter method(in my particular case)
MethodInfo mi = typeof(type).GetMethod("method1");
Type tt = typeof(type);
ParameterInfo[] param = mi.GetParameters();
object[] param = new object[] { //some code };
object mm= mi.Invoke(this, param);
MethodInfo mi2 = typeof(type).GetMethod("GetAwaiter");
var ss1= mi2.Invoke(mm,null);
on the last line i get an error: "object does not match target type"
Your code is more or less correct, but that exception is telling you that mm is not what you think it is. The type returned by your method1 is not the same as the type you have specified in the .GetMethod("GetAwaiter") line.
A safer bet would be to replace typeof(type) with mm.GetType().GetMethod("GetAwaiter"). I suspect that will actually return null, since mm.GetType() doesn't seem to be what you expect, but without seeing more code (in particular, what 'type' is and where the "method1" and "GetAwaiter" methods are actually declared) it's hard to give you much more guidance.
There is an error on this line
MethodInfo mi2 = typeof(type).GetMethod("GetAwaiter");
mm object has a different type, so you get an exception. Change the line to
MethodInfo mi2 = mm.GetType().GetMethod("GetAwaiter");
as Tim suggests.
It's better to use the Type.InvokeMember method since it's shorter and helps avoid errors like this. For example:
object mResult = this.GetType ().InvokeMember ("method1",
BindingFlags.InvokeMethod | BindingFlags.Instance, null, this,
new object[] { /* parameters here */ });
object awaiter = mResult.GetType ().InvokeMember ("GetAwaiter",
BindingFlags.InvokeMethod | BindingFlags.Instance, null, mResult, null);

How to call a method with arguments of different types using reflection in C#

I'm trying to call a function that takes two parameters (a boolean and a string) using .NET reflection in C#. However, with the following code i get an exception:
object[] paramList = new object[] { true, "Foo" };
Type wsType = typeof(MyWS);
MyWS inst = (MyWS)Activator.CreateInstance(wsType);
MethodInfo method = wsType.GetMethod(function); // function = the name of the function to be called
method.Invoke(inst, paramList);
This throws an ArrayTypeMismatchException ("Attempted to access an element as a type incompatible with the array.").
It seems that paramList is causing the exception, but I have no idea why?
The function I'm trying to call would be something like:
public bool EnableSchedule(bool enable, string password)
{
...
}
It doesn't seem like there is anything wrong with what you are doing - unless the problem lies in the "MyWS". I assume the class is public.
Meanwhile, try adding some binding flags to GetMethod(), like
wsType.GetMethod(function, BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance);

Invoking methods with optional parameters through reflection

I've run into another problem using C# 4.0 with optional parameters.
How do I invoke a function (or rather a constructor, I have the ConstructorInfo object) for which I know it doesn't require any parameters?
Here is the code I use now:
type.GetParameterlessConstructor()
.Invoke(BindingFlags.OptionalParamBinding |
BindingFlags.InvokeMethod |
BindingFlags.CreateInstance,
null,
new object[0],
CultureInfo.InvariantCulture);
(I've just tried with different BindingFlags).
GetParameterlessConstructor is a custom extension method I wrote for Type.
According to MSDN, to use the default parameter you should pass Type.Missing.
If your constructor has three optional arguments then instead of passing an empty object array you'd pass a three element object array where each element's value is Type.Missing, e.g.
type.GetParameterlessConstructor()
.Invoke(BindingFlags.OptionalParamBinding |
BindingFlags.InvokeMethod |
BindingFlags.CreateInstance,
null,
new object[] { Type.Missing, Type.Missing, Type.Missing },
CultureInfo.InvariantCulture);
Optional parameters are denoted by an ordinary attribute and are handled by the compiler.
They have no effect (other than a metadata flag) on the IL, and are not directly supported by reflection (except for the IsOptional and DefaultValue properties).
If you want to use optional parameters with reflection, you'll need to manually pass their default values.
I'll just add some code... because. The code isn't pleasent, I agree, but it is fairly straight forward. Hopefully this will help someone who stumbles accross this. It is tested, though probably not as well as you would want in a production environment:
Calling method methodName on object obj with arguments args:
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 function ArgumentListMatches is below, which basically takes the place of the logic 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 this has not been performance tested!
Also, this will not handle generic function or method calls. That makes this significantly more ugly (as in repeated GetMethod calls).
All questions disappear as you see your code decompiled:
c#:
public MyClass([Optional, DefaultParameterValue("")]string myOptArg)
msil:
.method public hidebysig specialname rtspecialname instance void .ctor([opt]string myOptArg) cil managed
As you see, optional parameter is a real separate entity that is decorated with specific attributes and has to be respected accordingly when invoking via reflection, as described earlier.
With the opensource framework ImpromptuInterface as of version 4 you can use the DLR in C# 4.0 to invoke constructors in a very late bound way and it's totally aware of constructors with named/optional arguments, this runs 4 times faster than Activator.CreateInstance(Type type, params object[] args) and you don't have 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"))
I know this is an old thread but just want to add this.
If you're not sure how many parameters exist for the method, you can do this dynamically instead:
var method = obj.GetType().GetMethod("methodName");
int? parameters = method?.GetParameters().Length;
var data = method?.Invoke(prop, (object?[]?)(parameters.HasValue ? Enumerable.Repeat(Type.Missing, parameters.Value).ToArray() : Array.Empty<object>()));
Hope this helps.

How do I use reflection to invoke a private method?

There are a group of private methods in my class, and I need to call one dynamically based on an input value. Both the invoking code and the target methods are in the same instance. The code looks like this:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
In this case, GetMethod() will not return private methods. What BindingFlags do I need to supply to GetMethod() so that it can locate private methods?
Simply change your code to use the overloaded version of GetMethod that accepts BindingFlags:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(this, new object[] { methodParams });
Here's the BindingFlags enumeration documentation.
BindingFlags.NonPublic will not return any results by itself. As it turns out, combining it with BindingFlags.Instance does the trick.
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
And if you really want to get yourself in trouble, make it easier to execute by writing an extension method:
static class AccessExtensions
{
public static object call(this object o, string methodName, params object[] args)
{
var mi = o.GetType ().GetMethod (methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance );
if (mi != null) {
return mi.Invoke (o, args);
}
return null;
}
}
And usage:
class Counter
{
public int count { get; private set; }
void incr(int value) { count += value; }
}
[Test]
public void making_questionable_life_choices()
{
Counter c = new Counter ();
c.call ("incr", 2); // "incr" is private !
c.call ("incr", 3);
Assert.AreEqual (5, c.count);
}
Microsoft recently modified the reflection API rendering most of these answers obsolete. The following should work on modern platforms (including Xamarin.Forms and UWP):
obj.GetType().GetTypeInfo().GetDeclaredMethod("MethodName").Invoke(obj, yourArgsHere);
Or as an extension method:
public static object InvokeMethod<T>(this T obj, string methodName, params object[] args)
{
var type = typeof(T);
var method = type.GetTypeInfo().GetDeclaredMethod(methodName);
return method.Invoke(obj, args);
}
Note:
If the desired method is in a superclass of obj the T generic must be explicitly set to the type of the superclass.
If the method is asynchronous you can use await (Task) obj.InvokeMethod(…).
Reflection especially on private members is wrong
Reflection breaks type safety. You can try to invoke a method that doesn't exists (anymore), or with the wrong parameters, or with too much parameters, or not enough... or even in the wrong order (this one my favourite :) ). By the way return type could change as well.
Reflection is slow.
Private members reflection breaks encapsulation principle and thus exposing your code to the following :
Increase complexity of your code because it has to handle the inner behavior of the classes. What is hidden should remain hidden.
Makes your code easy to break as it will compile but won't run if the method changed its name.
Makes the private code easy to break because if it is private it is not intended to be called that way. Maybe the private method expects some inner state before being called.
What if I must do it anyway ?
There are so cases, when you depend on a third party or you need some api not exposed, you have to do some reflection. Some also use it to test some classes they own but that they don't want to change the interface to give access to the inner members just for tests.
If you do it, do it right
Mitigate the easy to break:
To mitigate the easy to break issue, the best is to detect any potential break by testing in unit tests that would run in a continuous integration build or such. Of course, it means you always use the same assembly (which contains the private members). If you use a dynamic load and reflection, you like play with fire, but you can always catch the Exception that the call may produce.
Mitigate the slowness of reflection:
In the recent versions of .Net Framework, CreateDelegate beat by a factor 50 the MethodInfo invoke:
// The following should be done once since this does some reflection
var method = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
// Here we create a Func that targets the instance of type which has the
// Draw_ItemType method
var draw = (Func<TInput, Output[]>)_method.CreateDelegate(
typeof(Func<TInput, TOutput[]>), this);
draw calls will be around 50x faster than MethodInfo.Invoke
use draw as a standard Func like that:
var res = draw(methodParams);
Check this post of mine to see benchmark on different method invocations
Are you absolutely sure this can't be done through inheritance? Reflection is the very last thing you should look at when solving a problem, it makes refactoring, understanding your code, and any automated analysis more difficult.
It looks like you should just have a DrawItem1, DrawItem2, etc class that override your dynMethod.
Invokes any method despite its protection level on object instance. Enjoy!
public static object InvokeMethod(object obj, string methodName, params object[] methodParams)
{
var methodParamTypes = methodParams?.Select(p => p.GetType()).ToArray() ?? new Type[] { };
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
MethodInfo method = null;
var type = obj.GetType();
while (method == null && type != null)
{
method = type.GetMethod(methodName, bindingFlags, Type.DefaultBinder, methodParamTypes, null);
type = type.BaseType;
}
return method?.Invoke(obj, methodParams);
}
I think you can pass it BindingFlags.NonPublic where it is the GetMethod method.
Could you not just have a different Draw method for each type that you want to Draw? Then call the overloaded Draw method passing in the object of type itemType to be drawn.
Your question does not make it clear whether itemType genuinely refers to objects of differing types.
It should be noted that calling from a derived class can be problematic.
Error prone:
this.GetType().GetMethod("PrivateTestMethod", BindingFlags.Instance | BindingFlags.NonPublic)
Correct:
typeof(CurrentClass).GetMethod("PrivateTestMethod", BindingFlags.Instance | BindingFlags.NonPublic)
Read this (supplementary) answer (that is sometimes the answer) to understand where this is going and why some people in this thread complain that "it is still not working"
I wrote exactly same code as one of the answers here. But I still had an issue. I placed break point on
var mi = o.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance );
It executed but mi == null
And it continued behavior like this until I did "re-build" on all projects involved. I was unit testing one assembly while the reflection method was sitting in third assembly. It was totally confusing but I used Immediate Window to discover methods and I found that a private method I tried to unit test had old name (I renamed it). This told me that old assembly or PDB is still out there even if unit test project builds - for some reason project it tests didn't built. "rebuild" worked

Categories

Resources