views:

40

answers:

3

I have a method

String Foo<T> where T: WebControl

Now I do have a string like "hyperlink". What is want is to call Foo<Hyperlink> based on a mapping from the string to the generic.

How does the dictionary have to look like?

It ain't:

private Dictionary<string, Type> _mapping = new Dictionary<string, Type>()
{
      {"hyperlink", typeof(HyperLink)}
};

I want to access it like Foo<_mapping[mystring]> is that possible? If yes, how must be dictionary look like?

Edit: Accepted Solution

String _typename = "hyperlink";
MethodInfo _mi = typeof(ParserBase).GetMethod("Foo");
Type _type = _mapping[_typename];
MethodInfo _mig = _mi.MakeGenericMethod(_type);
return (String)_mig.Invoke(this, new object[] { _props }); // where _props is a dictionary defined elsewhere
// note that the first parameter for invoke is "this", due to my method Foo is not static
+1  A: 

What you want isn't possible, as that would be runtime (e.g. the dictionary could contain anything later).

If you want to manually generate it via runtime, you can do so, but you won't get the compile-time checking C# has on generics. You can to this via MethodInfo.MakeGenericMethod.

Like this:

var m = typeof(MyClass);
var mi = ex.GetMethod("Foo");
var mig = mi.MakeGenericMethod(_mapping["hyperlink"]);

//Invoke it
mig .Invoke(null, args);
Nick Craver
Ok then, how do I generate it via runtime? I do fill this dictionary manually, so I know which class derives from WebControl.
citronas
@citronas - I put a quick example for making a method generic, there's an equivalent if you need the class called MakeGenericType: http://msdn.microsoft.com/en-us/library/system.type.makegenerictype.aspx
Nick Craver
Thanks a lot, I was able to find a solution based on your sample, although I have nearly zero experience with relection =) I simplified my solution and edited it into my question, so that others may benefit from this thread.
citronas
+1  A: 

It isn't possible this way. Generics supports only compile-tipe binding.

Restuta
+1  A: 

No, you can't do that. Your generic type wants to create itself at compile time but it doesn't know what type it is til runtime. You can, however, use reflection.

Type untypedGeneric = typeof(Foo<>);
Type typedGeneric = untypedGeneric.MakeGenericType(_mapping[mystring]);
pdr