Monday, April 25, 2011

Runtime creation of generic Func<T>

I need to implement the method:

object GetFactory(Type type);

This method needs to return a Func<T> where typeparam 'T' is the 'type'.

So, my problem is that I don't know how to create a Func<?> at runtime using reflection. Activator.CreateInstance doesn't work because there are no constructors on delegates.

Any Ideas?

From stackoverflow
  • I think the usual approach would be to make the "dumb" version be the thing that you spoof at runtme, and then provide a helper extension method to provide the type-safe version on top of it.

    Craig Wilson : So, this is in the bowels of an IoC container, and I have to return the object as a strongly typed dependency, not necessarily knowing that what was requested was a Func (it could be a Uri or string).
  • You use Delegate.CreateDelegate, i.e. from a MethodInfo; below, I've hard-coded, but you would use some logic, or Expression, to get the actual creation method:

    using System;
    using System.Reflection;
    class Foo {}
    
    static class Program
    {
        static Func<T> GetFactory<T>()
        {
            return (Func<T>)GetFactory(typeof(T));
        }
        static object GetFactory(Type type)
        {
            Type funcType = typeof(Func<>).MakeGenericType(type);
            MethodInfo method = typeof(Program).GetMethod("CreateFoo",
                BindingFlags.NonPublic | BindingFlags.Static);
            return Delegate.CreateDelegate(funcType, method);
        }
        static Foo CreateFoo() { return new Foo(); }
        static void Main()
        {
            Func<Foo> factory = GetFactory<Foo>();
            Foo foo = factory();
        }
    }
    

    For non-static methods, there is an overload of Delegate.CreateDelegate that accepts the target instance.

    Craig Wilson : Mark, I don't actually know what T is. If I knew what T is, this would be easy.
    Marc Gravell : You mean within the non-generic method? I'll update...
    Craig Wilson : I modified the question to better state my problem.
    Craig Wilson : Not exactly what I needed , but this pushed me down the right path. Thanks for your help.
    Marc Gravell : 'twas the best I could do given the available information...
    Daniel Earwicker : Oooh, was playing with reflection the other day and wondered if there was a way to describe a generic type definition in code, and now I know: List<>, which presumably can only appear inside typeof?
    Marc Gravell : @Earwicker: correct; you simply omit all the type-args - for example, KeyValuePair<,> instead of KeyValuePair
  • you could create Expression objects instead of a func, and compile() the expression to get a Func delegate.

0 comments:

Post a Comment