What is BindingFlags.InvokeMethod meant for? - c#

I have the following code used to avoid a switch statement to decide which method to invoke, and it works with just the BindingFlags flags I have set, without InvokeMethod. What is InvokeMethod actually meant for and why is it not needed in the following code:
public enum PublishMethods
{
Method1,
Method2,
Method3
}
private void Form1_Load(object sender, EventArgs e)
{
InvokePublishMethod(PublishMethods.Method2);
}
private void InvokePublishMethod(PublishMethods publishMethod)
{
var publishMethodsType = this.GetType();
var method = publishMethodsType.GetMethod("Publish" + publishMethod, BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(this, null);
}
private void PublishMethod2()
{
MessageBox.Show("Method2!");
}

InvokeMethod isn't used by GetMethod, but it is used when you pass a BindingFlags to Type.InvokeMember.
BindingFlags is a strange kind of enum that combines three separate pieces of functionality (according to MSDN, 'accessibility', 'binding argument' and 'operation'). These three pieces of functionality don't make sense wherever a BindingFlags parameter is needed.

From the MSDN the InvokeMethod member:
Specifies that a method is to be invoked. This must not be a constructor or a type initializer.
It's used by the InvokeMember method.

Related

How to find private static methods in static class using reflection?

I have a static class and I want to find its private static methods using typeof(MyStaticClass).GetMethods() but it always shows me the public methods only.
How can I achieve this?
Use the overload of GetMethods that includes a BindingFlags parameter:
var methods = typeof(MyStaticClass)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
(I haven't included BindingFlags.Instance as you've explicitly said it's a static class; to find all methods in any class, include that as well.)

C# - GetMethod returns null

I have A class:
public abstract class A
{
}
And then I have B class that derives from it:
public sealed class B : A
{
public void SomeMethod()
{
var method = this.GetType().GetMethod("AddText");
}
private void AddText(string text)
{
...
}
}
Why is GetMethod returning null?
var methodInfo = this.GetType().GetMethod("AddText", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null);
Your method has a parameter, you need to use the overload that accepts a type array for the parameter types and the binding flags.
In .net Method signatures are based on their name, their return type, and their parameters.
So if your method has parameters you have to tell Reflection what parameter types it has via a Type[].
By default, Reflection will only search for public methods.
You need to pass BindingFlags.Instance | BindingFlags.NonPublic.

Why does GetMethod need BindingFlags as mandatory information in order to find methods?

Assuming I have this class with a private method:
public class Test
{
private void Method()
{
}
}
And this code:
var method1 = typeof(Test).GetMethod("Method"); // null
var method2 = typeof(Test).GetMethod("Method", BindingFlags.NonPublic | BindingFlags.Instance); // works!!
var method3 = typeof(Test).GetMethod("Method",BindingFlags.Instance); // null
Why are method1 and method3 null?
Why do I have to be specific with the BindingFlags in order to actually get the method? If it's because I can have multiple methods with the same name then what does the GetMethods exist for?
How specific do I need to be? In this case I needed to add that I'm looking for a non-public & instance method. Since not all of the BindingFlags values are straight forward, how do I know where I need to stop?
The Private modifier means "hide this method from outsiders", so by default GetMethods() returns only the public members.
1.method1 and method3 are null because it is specifically mentioned in this MSDN link that "You must specify Instance or Static along with Public or NonPublic or no members will be returned."
2.For using reflection you must know exactly what you are looking for otherwise you might get the wrong method to invoke.
3.As I already mentioned in No.1 answer, you must at-least specify "Instance or Static along with Public or NonPublic".

GetMethod returning null

I have an asp.net web page. This is the class implementing the page:
public partial class _Default : System.Web.UI.Page
{
private readonly string delegateName = "DynamicHandler";
protected void Page_Load(object sender, EventArgs e)
{
EventInfo evClick = btnTest.GetType().GetEvent("Click");
Type tDelegate = evClick.EventHandlerType;
MethodInfo method = this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate, this, method);
MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(btnTest, addHandlerArgs);
}
private void DynamicHandler(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I am trying to hook up an event handler dynamicly. For some reason method remains null and I can't figure out why. I have done this many times before and I can't figure out what I'm missing.
EDIT: I found that this.GetType() returns the type of the page ASP.default_aspx and not the actual type implementing the page. I don't really know how to get around this...
For the benefit of anyone else, GetMethod() can also return null if the arguments you passed do not match the arguments of the method you are trying to find. So, for example, if you are trying to find the method:
SomeMethod(int intParam, string stringParam)
You need to pass the parameter types to GetMethod:
type.GetMethod("SomeMethod", new[] { typeof(int), typeof(string) });
Or, if you want to specify special binding flags:
type.GetMethod("SomeMethod", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int), typeof(string) }, null);
As you've discovered in your edit, the actually ASPX page gets compiled into a class that inherits from _Default (where your code is located). So you need to make DynamicHandler (at least) protected rather than private.
Specify BindingFlags.FlattenHierarchy also:
this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
There are two things to be aware of.
(1) When you use:
this.GetType()
or equivalently just GetType(), the type which is returned is the actual run-time type of the actual instance. Since _Default is a non-sealed class, that type might very well be a more derived (more specialized type) than _Default, i.e. some class which has _Default as its direct or indirect base class.
If what you want is always the "constant" type _Default, use the typeof keyword, so use:
typeof(_Default)
instead of GetType(). This alone would solve your problem.
(2) Even if you specify BindingFlags.NonPublic, inherited private members are not returned. With your choice of binding flags, private methods declared in the same class (the derived class) are returned, but private methods inherited from base classes are not returned. However with internal and protected members, both the ones declared in the class itself and the ones declared in the base classes are returned.
This might make some sense, since a private method is not meant to be invoked from a derived class.
Changing the access level of your DynamicHandler method from private to e.g. protected (as suggested in the other answer) would be enough to solve your problem, as inherited protected members are selected when you use BindingFlags.NonPublic.
It is still interesting that you can't get the inherited private members with BindingFlags. Related thread C#: Accessing Inherited Private Instance Members Through Reflection. It is possible to write a method that searches all base types, of course, like:
static MethodInfo GetPrivateMethod(Type type, string name)
{
MethodInfo retVal;
do
{
retVal = type.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
if (retVal != (object)null)
break;
type = type.BaseType;
} while (type != (object)null);
return retVal;
}
That alone would also have solved your problem.

How to call private generic method in C# passing type in runtime

I tried code below in .NET 3.5 but mi is null.
How to call private generic method so that type parameter can be passed at runtime?
If SaveEntityGeneric is marked as public this code works OK but I dont wat to make it public since it is only used in other method in same class to pass this class type using GetType().
using System.Reflection;
public class Main1
{
static void Main()
{
new Class1().Test();
}
}
class Class1
{
public void Test()
{
var mi = GetType().GetMethod("SaveEntityGeneric", BindingFlags.NonPublic);
// why mi is null ?
var gm = mi.MakeGenericMethod(GetType());
gm.Invoke(this, null);
}
void SaveEntityGeneric<TEntity>()
{
}
}
The binding flags are tricky to get right on this. Use BindingFlags.NonPublic | BindingFlags.Instance.
var mi = GetType().GetMethod("SaveEntityGeneric",
BindingFlags.NonPublic | BindingFlags.Instance);
var gm = mi.MakeGenericMethod(GetType());
gm.Invoke(this, null);
Simply make it internal, that will prevent from usage that method outside the assembly

Categories