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
Related
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 do you get the argument value supplied to a closed/constructed generic method?
It's been a while since I haven't touched Reflection. All this used to be at the back of my, umm, whatever.
class Program
{
static void Main(string[] args)
{
new ConcreteFoo().GenericMethod<int>(5);
Console.ReadKey();
}
}
class ConcreteFoo
{
public void GenericMethod<Q>(Q q)
{
var method = MethodInfo.GetCurrentMethod();
var parameters = method.GetParameters();
if (parameters.Length > 0)
foreach (var p in parameters)
Console.WriteLine("Type: {0}", p.ParameterType);
// That still prints Q as the type.
// I've tried GetGenericArguments as well. No luck.
// I want to know:
// 1) The closed type, i.e. the actual generic argument supplied by the caller; and
// 2) The value of that argument
}
public void GenericMethodWithNoGenericParameters<Q>()
{
// Same here
}
}
class GenericFoo<T>
{
public void NonGenericMethod(T t) { /* And here*/ }
public void GenericMethod<Q>(Q q) { /* And here */ }
}
UPDATE
This question is absurd and hence closed by the asker. He wishes to retain it just to show his children how stupid daddy was, if they ever turned out to be C# programmers.
The short answer is typeof(Q).
The long answer (which tries to explain why you can't enumerate these types and you must write them specifically) goes like this:
Each generic method (which is more generic than it's declaring class) has corresponding, distinct MethodInfo instances for all of its (ever) touched particularizations and another MethodInfo for the "template"/open method.
You could use this to obtain what you want:
class ConcreteFoo {
public void GenericMethod<Q>(Q q) {
var method = MethodInfo.GetCurrentMethod();
var closedMethod = method.MakeGenericMethod(typeof(Q));
// etc
}
}
Why is that ?
It's because none of the "enumerating operations" in reflection return MethodInfo instances that refer to closed particularizations.
If you enumerate the static methods declared by ConcreteFoo like so:
var atTime1 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
ConcreteFoo.GenericMethod( true );
var atTime2 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
you will get identical results.
As far as GenericMethod and it's entourage of particularizations are concerned, you will get only the reflection object associated with GenericMethod (open variant).
atTime2 will not contain an extra MethodInfo referring to the freshly jitted GenericMethod< bool >.
But that not's really a bad thing, now is it ?
GetMethods() should return consistent results and not have its results vary in time.
The algebra of generic methods is actually quite nice when it comes to it's "navigation" operations:
All open MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = true
All closed MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = false
By calling .GetGenericMethodDefinition() on a closed MethodInfo you get the open one
By calling .MakeGenericType(params Type[] types) on an open MethodInfo you get whatever closed one you want (without being syntactically aware of what those types are and with the possibility of receiving an exception for not respecting the where clauses)
The same goes for the reflection operations that come from the current thread's perspective (rather than from that of the assemblies and types):
MethodBase MethodInfo.GetCurrentMethod()
and
StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
select frame.GetMethod();
never return the actual closed variants of generic methods (if any)
that are actually on the top, or throughout the current call stack.
In a way your question is not absurd, because, while in the case of GetCurrentMethod
you could easily replace it with GetCurrentMethod plus MakeGenericMethod plus the syntactically available typeof(Whatever), you can't say that about your callers.
So.. for non-generic methods you can always look at your stack and know precisely what are those methods' parameter types. The methods that invoked each other and eventually yours got invoked... But for generic ones (which are really truly closed, for I repeat it is illogical to think that a generic method that runs and calls another and was called by someone else (etc) is an open one) you can't find out the types of the parameters just like you can't learn the values of any such methods' local variables (which are deterministic but it would be a great flaw in performance to make that a possibility).
I'm trying to test private methods in a Unit test project. So far it's going great, but I hit a bump, when I have to test a method with an out parameter. The signature for that method is:
private bool GotSSI(out SSI ssi, RSI rsi)
{
~code omitted~
}
And the unittest (the part that is not working) looks like this:
SSI ssi = null;
object[] p = new object[]{ssi,rsi};
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool) privateTarget.Invoke("GotSSI",t,p);
The GotSSI method work. I've tested it in debug mode within the unit test and I can see that the 'ssi' out variable is set inside the method, before returning it's true or false value. But when the test returns to it's own code, the 'ssi' variable is still null. So the problem is that the object I created in the "GotSSI" method, is not parsed out of the PrivateObject invoke method.
Anyone knows what I am missing?
Update (Solution by Rafal)
Rafal's solution work perfectly and here is how I implemented the solution.
I created a delegate:
delegate bool GotSSIInternal(out SSI ssi, RSI rsi);
And when I have created the object I wanted to test, I build the delegate (target is the object i'm testing):
GotSSIInternal gotSSIInternal = (GotSSIInternal) Delegate.CreateDelegate(
typeof (GotSSIInternal),
target,
typeof(OfflineResolver).GetMethod("GotSSI", BindingFlags.NonPublic | BindingFlags.Instance));
After that is very simple to call the delegate:
actual = gotSSIInternal.Invoke(out ssi, rsi);
The solution is very simple and works like a charm.
Although the final solution that was accepted works, there is a much simpler way to do it. If you follow the link given in the accepted answer from Rafal, you will find a similar question to this one, with two answers. The second answer (with the most "useful" points) is the simpler of the two.
Here is a modified version of that answer specifically for a testing scenario:
//method to test is a private method of the class ClassTotest with signature
// TryGetCustomerData(List<Invoice> invoices, out CustomerData customerData)
//set up
var objToTest = new ClassToTest();
var invoices = GetInvoices();
CustomerData customerData = null;
//set up the arguments
var args = new object[] { invoices, customerData };
//get the MethodInfo of the method you want to test
var method = typeof(ClassToTest).GetMethod("TryGetCustomerData",
BindingFlags.NonPublic | BindingFlags.Instance);
//invoke it
var success = (bool)method.Invoke(objToTest, args);
//get back the customerData argument - the "out" parameter
var actual = args[1] as CustomerData;
your invocation of method with out parameter is wrong if you want to get the out value. See this on how to invoke it with reflection.
You need to ask yourself if you really need to test private methods? I personally do not test Private methods but it is all down to personal opinion (and it can get quite heated). There are numerous reasons / articles / opinions. A good SO thread can be found here.
An excerpt from the accepted answer is "A private method is an implementation detail that should be hidden to the users of the class. Testing private methods breaks encapsulation..."
The reason I do not test my private methods is because they are more likely to change than the public interface. If you cover all of your private methods it makes refactoring more complex (again, just my opinion). If you change a private method and the Public interface breaks you will know as your unit tests fail and you can then drill down.
That is just my opinion and I know many disagree so just putting it out there!
I can use PrivateObject to do this, although it is not technically a "return value", like:
object[] p = new object[] { null, rsi };
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool)privateTarget.Invoke("GotSSI", t, p);
SSI ssi = p[0];
Actually the type array can be omitted if the method overload can be determined without it:
object[] p = new object[] { null, rsi };
actual = (bool)privateTarget.Invoke("GotSSI", p);
SSI ssi = p[0];
Just do this: https://instance-factory.com/?p=738
ClassWithPrivateMethods instance = new ClassWithPrivateMethods();
PrivateObject privateObject = new PrivateObject(instance);
object[] args
= new object[] { "some value", null /* placeholder for out param */ };
privateObject.Invoke("PrivateMethodHavingOutParameter", args);
var outParameterValue = args[1];
My intention is to investigate the "Methods" of a Type using reflection in order to verify the following :
The Methods should be instance methods and public.
Takes the parameter "params" and void in nature.
The Method does not makes recursive call.
I started as :
static void ProcessMethodInfo(Type t)
{
MethodInfo[] info = t.GetMethods();
foreach (MethodInfo mi in info)
{
// How to check the conditions here ?
}
}
But I don't know how to proceed further. Help is needed.
Well, if by 3 you mean the method under inspection should be non-recursive; then that is a pain - you'd need to parse the IL. But for the others;
Type type = ...
var qry = from method in type.GetMethods(
BindingFlags.Instance | BindingFlags.Public)
where method.ReturnType == typeof(void)
let parameters = method.GetParameters()
where parameters.Length == 1
&& parameters[0].ParameterType.IsArray
&& Attribute.IsDefined(parameters[0], typeof(ParamArrayAttribute))
select method;
foreach (var method in qry)
{
Console.WriteLine(method.Name);
}
mi.IsStatic, etc - read help
Determining if a parameter uses "params" using reflection in C#?
http://www.codeproject.com/KB/cs/sdilreader.aspx
ALL: use google ;)
I don't think you'll be able to detect item 3 using reflection.
Check the following members of the MethodInfo class:
IsPublic
IsStatic
ReturnType
GetParameters() method
In order to be able to check whether the method is recursive, I think you'll need something more then just simple reflection.
Is there something like Python's getattr() in C#? I would like to create a window by reading a list which contains the names of controls to put on the window.
There is also Type.InvokeMember.
public static class ReflectionExt
{
public static object GetAttr(this object obj, string name)
{
Type type = obj.GetType();
BindingFlags flags = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.GetProperty;
return type.InvokeMember(name, flags, Type.DefaultBinder, obj, null);
}
}
Which could be used like:
object value = ReflectionExt.GetAttr(obj, "PropertyName");
or (as an extension method):
object value = obj.GetAttr("PropertyName");
Use reflection for this.
Type.GetProperty() and Type.GetProperties() each return PropertyInfo instances, which can be used to read a property value on an object.
var result = typeof(DateTime).GetProperty("Year").GetValue(dt, null)
Type.GetMethod() and Type.GetMethods() each return MethodInfo instances, which can be used to execute a method on an object.
var result = typeof(DateTime).GetMethod("ToLongDateString").Invoke(dt, null);
If you don't necessarily know the type (which would be a little wierd if you new the property name), than you could do something like this as well.
var result = dt.GetType().GetProperty("Year").Invoke(dt, null);
Yes, you can do this...
typeof(YourObjectType).GetProperty("PropertyName").GetValue(instanceObjectToGetPropFrom, null);
There's the System.Reflection.PropertyInfo class that can be created using object.GetType().GetProperties(). That can be used to probe an object's properties using strings. (Similar methods exist for object methods, fields, etc.)
I don't think that will help you accomplish your goals though. You should probably just create and manipulate the objects directly. Controls have a Name property that you can set, for example.