views:

164

answers:

1

I wonder if C# (or the underlying .NET framework) supports some kind of "generic delegate instances": that is a delegate instance that still has an unresolved type parameter, to be resolved at the time the delegate is invoked (not at the time the delegate is created). I suspect this isn't possible, but I'm asking it anyway...

Here is an example of what I'd like to do, with some "???" inserted in places where the C# syntax seems to be unavailable for what I want. (Obviously this code doesn't compile)

class Foo {
  public T Factory<T>(string name) {
    // implementation omitted
  }
}

class Test {
  public void TestMethod()
  {
    Foo foo = new Foo();
    ??? magic = foo.Factory; // No type argument given here yet to Factory!
                             // What would the '???' be here (other than 'var' :) )?
    string aString = magic<string>("name 1"); // type provided on call
    int anInt = magic<int>("name 2"); // another type provided on another call

    // Note the underlying calls work perfectly fine, these work, but i'd like to expose
    // the generic method as a delegate.
    string aString2 = foo.Factory<string>("name 1");
    int anInt2 = foo.Factory<int>("name 2");
  }
}

Is there a way to actually do something like this in C#? If not, is that a limitation in the language, or is it in the .NET framework?

Edit: The reason I ask is because I'd like to pass the delegate to a function in another assembly, and don't want to require that other assembly having to reference any particular type (the "Foo" class in my example). I was hoping to bend the standard Func<> delegate in a way so it would fit the "???" part.

+4  A: 

This cannot be done, since what you're asking is declaring a variable (magic) of an unclosed generics type.

One can work with unclosed generics but only at the type level, e.g.:

delegate T FactoryDelegate<T>(string name);

var magicType = typeof (FactoryDelegate<>);

and then "close" the type at a later point:

var stringMagic = magicType.MakeGenericType(typeof(string));

Update: that said, here's a sample on how you can use the above technique to also work with unclosed method "types". Still not as elegant as it would be if we could assign unclosed types though..:

    public class UnclosedMethod
    {
        private readonly MethodInfo _method;

        public UnclosedMethod(Type type, string method)
        {
            _method = type.GetMethod(method);
        }

        public T Invoke<T>(string name)
        {
            var fact = _method.MakeGenericMethod(typeof(T));
            return (T)fact.Invoke(this, new object[] { name });
        }
    }

And then in code do this:

var magic = new UnclosedMethod(typeof(Foo), "Factory");
var x = magic.Invoke<string>("bar");
Peter Lillevold
thanks for the answer, I already suspected something like that. That leaves open the second part of the question: "is that a limitation in the C# language, or is it in the .NET framework".
Luc C