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
I know I can iterate through all locally defined variables in a method using MethodInfo.GetMethodBody().LocalVariables.
But if I define a method as:
public static void somemethod( int someint )
{
int test = 1;
HM.M(() =>
{
test = 2;
});
}
The anonymous method can access someint and test as closures, but GetMethodBody().LocalVariables will be empty.
Is there a way to use reflection to detect the closures?
Well, I found the answer. A closure in c# is implemented by the compiler with a compiler-generated class. The compiler generates a class where it copies all variables that will be accessible in the method, and the method itself is encapsulated in this class. The external variables values are copied to the class.
So, in my example above, the M method has the signature:
public void M( Action method )
The steps to get the list of closures are:
MethodInfo mi = method.Method;
FieldInfo[] fields = mi.DeclaringType.GetFields
(
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.Static
);
DeclaringType will be the compiler-generated class used to implement the closures.
In the fields array all closures will be listed.
To get the VALUES of the closures is another story, but it is not part of this question.
EDIT:
As pointed out by #leppie, get the values is easy:
object res = fields[ 0 ].GetValue( method.Target );
In the following code snippet I'm trying to use the 'IsDefined' method of a purpose-created model to see if I've already added the given type to the model. However, it always returns true, and inspection of the types known to the model after calling IsDefined shows that the type has been added to the model during the call. This seems to make IsDefined redundant, or am I missing something?
Version is 2.0.0.668.
private static void FillSignatureModel(RuntimeTypeModel Model, Object SignedObject) {
var lBinding = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
var lType = SignedObject.GetType();
// Already sorted
if (Model.IsDefined(lType)) return;
var lProtoType = Model.Add(lType, false);
...
Secondary question: Is there a better way of reporting Protobuf.net bugs - not that I ever expected to need one ;-)
I have a class:
class A {
public string a = "A-val" , b = "B-val";
}
I want to print the object members by reflection
//Object here is necessary.
Object data = new A();
FieldInfo[] fields = data.GetType().GetFields();
String str = "";
foreach(FieldInfo f in fields){
str += f.Name + " = " + f.GetValue(data) + "\r\n";
}
Here is the desired result:
a = A-val
b = B-val
Unfortunately this did not work. Please help, thanks.
Once fixed to get rid of the errors (lacking a semi-colon and a bad variable name), the code you've posted does work - I've just tried it and it showed the names and values with no problems.
My guess is that in reality, you're trying to use fields which aren't public. This code:
FieldInfo[] fields = data.GetType().GetFields();
... will only get public fields. You would normally need to specify that you also want non-public fields:
FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
(I hope you don't really have public fields, after all...)
Remember when you write fields like :
public string VarName{ get; set;}
Then actually you have this code(this is what reflection see) :
private string _varName;
public string get_VarName(){
....
}
public void set_VarName(strig value){
....
}
As #Stanislav say, you must keep in mind the backing fields generated by the compiler for properties. If you want to exclude these fields you can use the following code:
FieldInfo[] fields = data.GetType()
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
.ToArray();
I want to call Type.GetFields() and only get back fields declared as "public const". I have this so far...
type.GetFields(BindingFlags.Static | BindingFlags.Public)
... but that also includes "public static" fields.
type.GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.IsLiteral);
Trying checking whether FieldInfo.Attributes includes FieldAttributes.Literal. I haven't checked it, but it sounds right...
(I don't think you can get only constants in a single call to GetFields, but you can filter the results returned that way.)
Starting from .NET 4.5 you can do that
public class ConstTest
{
private const int ConstField = 123;
public int GetValueOfConstViaReflection()
{
var fields = this.GetType().GetRuntimeFields();
return (int)fields.First(f => f.Name == nameof(ConstField)).GetValue(null);
}
}
I checked and it looks like fields has all private consts.