This is best explained using code. I have a generic class that has a method that returns an integer. Here is a simple version for the purposes of explaining...
public class Gen<T>
{
public int DoSomething(T instance)
{
// Real code does something more interesting!
return 1;
}
}
At runtime I use reflection to discover the type of something and then want to create an instance of my Gen class for that specific type. That is easy enough and done like this...
Type fieldType = // This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);
I now want to create an Expression that will take as a parameter an instance of the generic type and then calls the DoSomething method of that type. So I want the Expression to effectively perform this...
int answer = genericInstance.DoSomething(instance);
...except I do not have the 'instance' until some point later at runtime and the genericInstance is the generated type as can be seen above. My attempt at creating the Lambda for this is as follows...
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var x = Expression.Lambda<Func<genericType, fieldType, int>>
(Expression.Call(p1, mi, p2),
new[] { p1, p2 }).Compile();
...so that later on I can call it with something like this...
int answer = x(genericInstance, instance);
Of course, you cannot provide Func with instance parameters and so I have no idea how to parameterize the Lambda generation. Any ideas?
I think you would just use the
Expression.Lambda
that takes the delegate type as a type rather then as a generic, and create your Func on the fly like you are withGen<>
:This will return a Delegate rather than a strongly typed
Func
, but you can of course cast it if needed (and seemingly difficult if you don't know what you are casting to), or dynamically invoke it usingDynamicInvoke
on it.EDIT:
This seems to work without the need of a dynamic invoke.
EDIT 2:
A greatly simplified version:
It's better to to accept an
object
and useconvert
to a known type.Here is an example, how to build access to a property by name on unknown depth:
It avoids extra costs of DynamicInvoke when type of delegate is unknown at compile time.
This answer only applies if you are using .NET 4.0.
If you make
genericInstance
dynamic
instead ofobject
, you can then call theDoSomething
method on it directly, and the dynamic language runtime will take care of everything for you.If you need to keep this class structure (
Gen<T>
), then I don't see an easy way around the fact that you don't know the typeT
at compile time. If you want to call the delegate, you either have to know its full type at compile time, or you need to pass in the parameters as objects.Using
dynamic
gets you to hide the complexity of getting theMethodInfo
, etc., and gives you excellent performance. The one drawback vs.DynamicInvoke
that I see is that I believe you get the initial overhead of resolving the dynamic call once for every call site. The bindings are cached so that they run very fast from the second time onwards if you call it on objects with the same type.