Reputation: 325
I know there are already questions like this, but I seriously just do not understand the answers (and I can't seem to comment on them).
I am completely new to reflection, and fairly new to delegates as well, so this is quite difficult for me.
A while ago I used reflection (for the first time) to get a method, I did it like this (simplified):
object perlinObj;
MethodInfo PerlinMethod = null;
//...
ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
perlinObj = constructor.Invoke(new object[] { });
PerlinMethod = type.GetMethod("GetValue", new Type[] { typeof(Vector3) });
//...
float PerlinFunction(Vector3 pos)
{
return (float)((Double)PerlinMethod.Invoke(perlinObj, new object[] { pos }));
}
This works, but the problem is that it's a lot slower than just calling the method directly. So I thought, maybe I could assign it to a delegate somehow, and then call the delegate instead of using invoke, which I assume would be faster. (it is, right?)
But I cannot find how to do this. I don't understand the documentation on msdn: http://msdn.microsoft.com/en-us/library/ms228976.aspx (I'm not even sure they are dooing the same as I'm trying to do), nor do I understand what I have to do exactly from reading this: Assign method to delegate through reflection.
(And what I tried didn't work)
So can anyone explain to me what I have to do in the example code I provided?
Upvotes: 3
Views: 1473
Reputation: 1062540
To do this the "easy" way, you need to know the target more exactly than object
; i.e. instead of:
object perlinObj;
you would need:
SomeType perlinObj;
Then, instead of storing the MethodInfo
, we use Delegate.CreateDelegate
to make a delegate - note I'm using int
here in place of Vector3
for my convenience:
Func<SomeType, int, float> PerlinMethod;
//...
PerlinMethod = (Func<SomeType, int, float>) Delegate.CreateDelegate(
typeof(Func<SomeType, int, float>),
null,
type.GetMethod("GetValue", new Type[] { typeof(int) }));
//...
float PerlinFunction(int pos)
{
return PerlinMethod(perlinObj, pos);
}
Note that if the target instance will never change, you can simplify:
Func<int, float> PerlinMethod;
//...
PerlinMethod = (Func<int, float>) Delegate.CreateDelegate(
typeof(Func<int, float>),
perlinObj,
type.GetMethod("GetValue", new Type[] { typeof(int) }));
//...
float PerlinFunction(int pos)
{
return PerlinMethod(pos);
}
If you can't do that, then it would be necessary to use more advanced meta-programming; either ILGenerator
or Expression
:
Func<object, int, float> PerlinMethod;
//...
var target = Expression.Parameter(typeof(object));
var arg = Expression.Parameter(typeof(int));
var call = Expression.Call(
Expression.Convert(target, type),
type.GetMethod("GetValue", new Type[] { typeof(int) }),
arg);
PerlinMethod = Expression.Lambda<Func<object,int,float>>(
call, target, arg).Compile();
Upvotes: 3