How do you call it?

Where we’re at

Following on from last time, we have our MethodInfo object and now need to actually invoke it. However we want to do this in a way that is as clean, safe and performant as possible.

Keeping it simple

We could simply call invoke on the MethodInfo object:

var foo = (Foo)methodInfo.Invoke(fooFactory, new object[] { 42 });

Last week, we put a lot of effort into trying to make what we were doing as safe as possible, so to throw away all the safety on the final hurdle seems rather silly. No type checking on the method’s parameters, an ugly cast of the return value to (Foo), and a fairly serious performance overhead make this solution less than ideal.

A nicer way

We can use System.Linq.Expressions to compile ourselves a Func<int, Foo> representing the method we wish to invoke:

var parameter = Expression.Parameter(typeof (int));
var lambda = Expression.Lambda<Func<int, Foo>>(
	Expression.Call(
		Expression.Constant(fooFactory), 
		methodInfo, 
		parameter),
	parameter);
var getFoo = lambda.Compile();
var foo = getFoo(42);

And this works… almost.

For reasons that I won’t go into deeply here, System.Linq.Expressions doesn’t deal with inheritance; it covers only a subset of language features and inheritance is not one of them. If we’re using an interface or base class for fooFactory then this will fail when we try to construct to Func.

The work around for this restriction is extremely simple though, we make the normal compiler do the work with inheritance by wrapping the call with our own concrete method.

private Foo GetFoo<T>(int id)
	where T : FlagBase
{
	return fooFactory.GetFoo<T>(id);
}

Since we’re now compiling this call to a Func<int, Foo> we can do this ahead of time and store the result, failing fast if anything is wrong and allowing us to invoke it repeatedly while avoiding the performance penalties associated with reflection. This leaves our full code looking like:

public abstract class FlagBase
{
	private readonly Func<int, Foo> getFoo;
	private readonly IFooFactory fooFactory = new FooFactory();
	
	public FlagBase()
	{
		var runtimeType = this.GetType();
		Func<int, Foo> methodGroup = GetFoo<FlagBase>;
		var methodInfo = methodGroup.Method
			.GetGenericMethodDefinition()
			.MakeGenericMethod(runtimeType);
		
		var parameter = Expression.Parameter(typeof (int));
		var lambda = Expression.Lambda<Func<int, Foo>>(
			Expression.Call(
				Expression.Constant(this),
				methodInfo, 
				parameter),
			parameter);
		
		this.getFoo = lambda.Compile();
	}
	
	public void Frobnicate()
	{
		var foo = getFoo(42);
		// ...
	}
	
	private Foo GetFoo<T>(int id)
		where T : FlagBase
	{
		return fooFactory.GetFoo<T>(id);
	}
}

Conclusion

What we were trying to do wasn’t particularly pretty and I certainly wouldn’t want to have to do it regularly, but as I mentioned last week this was about striking a balance between doing this strictly with the appropriate information at compile time, and making our API easier and cleaner to consume. Something like this is very much down to personal preference / style but I’m happy with the compromises that have been made, and with a good suite of tests I’m confident that the behaviour of this ‘hack’ is safe and reliable.