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 );
Related
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'm looking for a way to avoid FieldInfo.Get/SetValue overhead, and access memory directly for a few select, known ahead of time, primitive types. (Most specifically, I'm looking to avoid any memory allocations in our custom serializer)
Basically, here's what the official way allows me to do:
System.Object o = someobject;
int inOut = 0;
var type = o.GetType();
var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (var fi in fieldInfos) {
fi.SetValue(o, inOut);
inOut = (int)fi.GetValue(o);
}
And here's roughly what I'd like to do:
foreach (var fi in fieldInfos) {
fixed(int* ip = o.basePointer + fi.fieldOffset) {
*p = inOut;
inOut = *p;
}
}
I would use this only for Int32, Single, and possibly bools. I'm primarily interested in getting this working on Mono, so if there's anything Mono specific available, that'd be fine.
Note: I'm well aware of the "you shouldn't be doing this", and "have you profiled it" etc. I know, and I have, which is why I'm looking into this. We have a very specific case, where we control all variables (and all code), but we would like it to work on any 'normal' class without requiring additional markup or explicit struct layout.
EDIT: I should point out that I'm not able to emit dynamic code to solve this. I'm ok with a solution requiring me to write and assemble IL up-front though.
I'm well aware of the "you shouldn't be doing this"
That is good - I'll skip this part of the explanation then, and go straight to a way of accessing fields that avoids memory allocation, while staying within the limits of managed code.
You can use LINQ expressions to construct a Func<ObjType,int> for a getter and Action<ObjType,int> for a setter. Calling these functors would let you get or set int fields as if you were accessing their methods directly.
Here is how you can make a wrapper-free getter:
public class Test
{
public int myfield;
public static void Main()
{
// Make a parameter expression to represent the object
var argExpr = Expression.Parameter(typeof(Test), "a");
// Get the field of your object (the same way as in your first example)
var field = typeof(Test).GetField("myfield", BindingFlags.Public | BindingFlags.Instance);
// Make an expression accessing the field from the parameter
var fieldExpr = Expression.Field(argExpr, field);
// Compile the expression into a functor
var getter = (Func<Test,int>)Expression.Lambda(fieldExpr, argExpr).Compile();
// Construct a test object
var tmp = new Test {myfield = 123};
// Use a wrapper to avoid "boxing"/"unboxing" of "GetValue"
int res = getter(tmp);
Console.WriteLine("Res={0}", res);
}
}
Demo on ideone.
Construct the setter in a similar way, using one more parameter of type int, and Expression.Assign. The resultant lambda will compile into an Action<Test,int> rather than Func<Test,int>, because setters do not return value.
You say, that you can't use dynamic code generation. Here are some other ideas:
If you can work with properties instead of fields, create a delegate to the property getter (https://stackoverflow.com/a/724427).
Generate IL code for your serializer at build time. Compile that into an assembly that you can load at runtime. Just generate accessor code for each and every field. I think you can access private members in IL when FullTrust and SkipVerification permissions are present.
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).
For example, PHP code:
$test = "hello";
${$test} = $test;
echo $hello; // return hello
How to do this in C#? Thanks in advance.
UPD: Dynamic variable in C#? - here is an answer.
This isn't supported in C#. You could use an ExpandoObject and set a member on it, but it's not quite the same as the PHP code. You'll still need to refer to the ExpandoObject by a variable name.
dynamic myObject = new ExpandoObject();
string test = "Hello";
((IDictionary<string, object>)myObject).Add(test, test);
Console.WriteLine(myObject.Hello);
Nonetheless, this doesn't help with code clarity. If all you want to do is map a name to a value you can use a Dictionary, which is really what ExpandoObject uses internally, as demonstrated by the cast in the code above.
C# is not designed for that sort of thing at the language level. You will have to use reflection to achieve that, and only for fields, not local variables (which cannot be accessed via reflection).
Such dynamic access to class members can be achieved via reflection.
class Foo
{
string test;
string hello;
void Bar()
{
test = "hello";
typeof(Foo).InvokeMember( test,
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField,
null, this, new object[] { "newvalue" } );
}
}
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.