Why can't I call this method via string? - c#

Question from a Reflection newbie. I have a method in a Windows Form:
private void handleOrderCode()
{
//...do stuff
}
Which I am trying to call in the following manner:
Type t = this.GetType();
MethodInfo mi = t.GetMethod("handleOrderCode");
if (mi != null) mi.Invoke(this, null);
I have confirmed that "this" is not null. The space where the string "handleOrderCode" has been hardcoded is to be replaced with a string variable when this works. However, at present "mi" is always null when it evaluates in the if statement in the final line.
So what am I doing wrong?

You need to specify binding flags:
using System.Reflection;
t.GetMethod("handleOrderCode", BindingFlags.Instance | BindingFlags.NonPublic)
Because overload without any flag means:
BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance
i.e. will not return any non-public (private, protected, etc) members.

The parameterless overload of Type.GetMethod only looks for public methods:
Searches for the public method with the specified name.
You need to specify an appropriate BindingFlags value to another overload instead:
MethodInfo method = t.GetMethod("handleOrderCode",
BindingFlags.Instance | BindingFlags.NonPublic);
Note that you need to specify "instance" or "static" here (or both), not just "non-public". If you want to look for public methods as well, you have to include that too.
Another alternative is just to make your method public :)
(Additionally, I'd suggest renaming it to HandleOrderCode to be more conventional, idiomatic C#.)

try:
Type t = this.GetType();
MethodInfo mi = t.GetMethod("handleOrderCode",
BindingFlags.NonPublic | BindingFlags.Instance);
if (mi != null) mi.Invoke(this, null);

Related

MethodInfo always null when geting Type from instance

Can someone explain me, why here I get the correct MethodInfo:
MethodInfo mi = typeof(ContextTimerMode).GetMethod(_vo.Phase, BindingFlags.Instance | BindingFlags.NonPublic);
if (mi != null)
{
mi.Invoke(this, new object[] { btns, vo });
}
While trying to get it directly from instance returns always null?:
MethodInfo mi = (this as ContextTimerMode).GetType().GetMethod(_vo.Phase, BindingFlags.Instance | BindingFlags.NonPublic);
// mi always null
if (mi != null)
{
mi.Invoke(this, new object[] { btns, vo });
}
The code above is from ContextTimerMode.
this is a class that has ContextTimerMode as base class;
Actually I couldn't find a reason why it returns a null for sometime as I was using second method and I was debugging and making sure _vo.Phase string has correct name of method so I tried first method and it worked out.
Also when debugging this was showing that this is instance not of ContextTimerMode but a type that has a base of ContextTimerMode - so that is why I tried with (this as ContextTimerMode).GetType()...
That is because even if you do this:
(this as ContextTimerMode).GetType()
resulting type will not be ContextTimerMode, but will be the type inherited from ContextTimerMode (so, actual type of this, same as if you did this.GetType()). GetType() always returns actual type, even if you use it on variable declared as some base type. You are trying to get private, instance method of that type. Your inherited type really does not contain this method, so GetMethod correctly returns null.
If you want to work around this, you can manually walk hierarchy, like this:
static MethodInfo GetMethod(Type type, string methodName, BindingFlags flags) {
var mi = type.GetMethod(methodName, flags);
if (mi != null)
return mi;
if (type.BaseType != null)
return GetMethod(type.BaseType, methodName, flags);
return null;
}
The this keyword is redundant. You can just use GetType() internally and it will refer to your class.
_vo.Phase
must be the correct case and you don't need BindingFlags.Instance. I would remove BindingFlags.NonPublic as well and change the method access modifier to public to see if GetMethod() can actually find it.
You can always use GetMethods() to enumerate the available methods in the class. Maybe even use a linq query to get the MethodInfo object you want.

how to prevent getmethods from retrieve a specific method

I have a static class with private functions, I want to get all functions except one. I tried using Ignorecase but i get an overload exception... I do it exactly like many examples online but I get an error and I dont know why...am I missing something?
//Example
static MethodInfo[] allFuncs ;
static Type myType = typeof(myClass);
allFuncs = myType.GetMethods("innerFunction",
BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Static);
If you want all methods except one with a particular name, you can use Enumerable.Where to filter:
allFuncs = typeof(MyClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
.Where(method => !method.Name.Equals(
"innerFunction", StringComparison.OrdinalIgnoreCase));

Proper use of Reflection and binding flags

I want to modify the below code to be able to use a private method
//use reflection to Load the data
var method =
typeof(MemberDataFactory)
.GetMethod("LoadData")
.MakeGenericMethod(new [] { data.GetType() })
.Invoke(this, null);
Ive tried the following with no luck:
//use reflection to Load the data
var method =
typeof(MemberDataFactory)
.GetMethod("LoadData")
.MakeGenericMethod(new [] { data.GetType() })
.Invoke(this, BindingFlags.Instance | BindingFlags.NonPublic, null , null, null);
Also what is "var" in terms of this code? Id prefer to specify its type instead of using var.
Thanks!
You want to use this overload of Type.GetMethod(), which is where you pass your binding flags. The default .GetMethod(string) only looks for public methods, so it returns null, hence your null reference exception.
Your code should be something more like:
var method =
typeof(MemberDataFactory)
.GetMethod("LoadData", BindingFlags.Instance | BindingFlags.NonPublic) // binding flags go here
...

How can we get reference to current HttpRuntime?

Can anybody tell me what is this code doing:
PropertyInfo p = typeof(HttpRuntime).GetProperty("FileChangesMonitor",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
object o = p.GetValue(null, null);
FieldInfo f = o.GetType().GetField("_dirMonSubdirs",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase);
object monitor = f.GetValue(o);
MethodInfo m = monitor.GetType().GetMethod("StopMonitoring",
BindingFlags.Instance | BindingFlags.NonPublic);
m.Invoke(monitor, new object[] { });
How did the person get these reflection field names?
Effectively, the code is doing the equivalent of:
dynamic o = HttpRuntime.FileChangesMonitor;
dynamic monitor = o._dirMonSubdirs;
monitor.StopMonitoring();
The BindingFlags.NonPublic allow, through the use of reflection, accessing nonpublic fields. Without reflection, the above code would generate a compiler error.
The reflection field names can be obtained through a debugger, or types can be enumerated through reflection. For instance, to get all public and nonpublic static fields of a type X, you could use:
MemberInfo[] mi = typeof(X).GetType().FindMembers(MemberTypes.Property,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
(a, b) => true, // don't filter
null);
Note that using reflection to access nonpublic members is generally considered poor practice, since doing so relies on implementation mechanics that are not guaranteed and that are allowed to change from version to version and between implementations.

How can I get a list of the underlying delegates from an event using reflection?

First, GetInvocationList() won't work, because I want to be able to get to them from outside the class. I assume it will work with some reflection magic, and that's what I'm trying to figure out.
Here's what I have right now:
fooEventDispatcher.GetType().GetField("FooEvent", BindingFlags.Instance | BindingFlags.NonPublic);
var field = fieldInfo.GetValue(fooEventDispatcher);
I just don't know what to do with field. Any ideas?
This should work:
var fieldInfo = fooEventDispatcher.GetType().GetField(
"FooEvent", BindingFlags.Instance | BindingFlags.NonPublic);
var eventDelegate = fieldInfo.GetValue(fooEventDispatcher) as MulticastDelegate;
if (eventDelegate != null) // will be null if no subscribed event consumers
{
var delegates = eventDelegate.GetInvocationList();
}
Also you should use typeof(SomeFooClass) instead of fooEventDispatcher.GetType() if the type is already known at compile time (which I assume it is).

Categories