Reputation: 40395
I was going over a Joel Pobar's Dodge Common Performance Pitfalls to Craft Speedy Applications article on Reflection and I was looking at a particular piece of code that isn't compiling (slightly modified to narrow down to the specific error, because his example had more errors):
MethodInfo writeLine = typeof(Console).GetMethod("WriteLine");
RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
DynamicMethod dm = new DynamicMethod(
"HelloWorld", // name of the method
typeof(void), // return type of the method
new Type[]{}, // argument types for the method
false); // skip JIT visibility checks
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, world");
il.Emit(OpCodes.Call, myMethodHandle); // <-- 2 errors here
il.Emit(OpCodes.Ret);
The errors are:
Program.cs(350,13): error CS1502: The best overloaded method match for 'System.Reflection.Emit.ILGenerator.Emit(System.Reflection.Emit.OpCode, byte)' has some invalid arguments
Program.cs(350,35): error CS1503: Argument '2': cannot convert from 'System.RuntimeMethodHandle' to 'byte'
The ILGenerator
can Emit
with a MethodInfo
, but it doesn't seem to support MethodHandle
... does anybody know how to get this sample to work?
Upvotes: 3
Views: 3429
Reputation: 710
Through this library on Nuget.org: ClassWrapper
It creates wrappers for types that internally uses dynamically generated methods. So no reflection used (only into the ClassWrapperDescriptor.Load method to generate the dynamic expressions)
Given, e.g. e class named SampleClass
//Create the class wrapper descriptor, this can be cached and reused!
var classWrapperDescriptor = new ClassWrapperDescriptor(typeof(SampleClass));
//Initialize the descriptor
classWrapperDescriptor.Load();
//Create the instance of our object
object instance = new SampleClass();
//Create an instance of the wrapper
var classWrapper = classWrapperDescriptor.CreateWrapper(instance);
//Set a property
classWrapper.Set("StringProperty","test");
//Get a property
var stringPropertyValue = classWrapper.Get<string>("StringProperty");
//Invoke a method without return statement
classWrapper.Invoke("ParamMethod", "paramValue");
//Invoke a method witho return statement
var result = classWrapper.Invoke<int>("ReturnMethod", "paramValue");
Any feedback on this library is really appreciated!
Upvotes: 0
Reputation: 1064104
Like so?
MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new Type[] {typeof(string)});
RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
DynamicMethod dm = new DynamicMethod(
"HelloWorld", // name of the method
typeof(void), // return type of the method
new Type[] { }, // argument types for the method
false); // skip JIT visibility checks
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, world");
il.EmitCall(OpCodes.Call, writeLine, null);
il.Emit(OpCodes.Ret);
// test it
Action act = (Action)dm.CreateDelegate(typeof(Action));
act();
Changes:
GetMethod
to find the (string)
overload (otherwise it is an ambiguous match)MethodInfo
, not the handle (since that is what ILGenerator
wants)EmitCall
(the other might have worked too, but I know this way works)Upvotes: 3