Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass variable of type "Type" to generic parameter

Tags:

c#

generics

I'm trying to do this:

Type type = Type.GetType(string.Format("Gestor.Data.Entities.{0}, Gestor.Data", e.Item.Value));
MetaDataUtil.GetColumnasGrid<type>();

but it's not working, do you have any idea how I could do this?

like image 752
ryudice Avatar asked Feb 11 '10 20:02

ryudice


People also ask

Can dynamic type be used for generic?

Not really. You need to use reflection, basically. Generics are really aimed at static typing rather than types only known at execution time.

Which types can be used as arguments of a generic type?

The actual type arguments of a generic type are. reference types, wildcards, or. parameterized types (i.e. instantiations of other generic types).

How do you indicate that a class has a generic type parameter?

A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.

How do you define a generic type in TypeScript?

Generics allow creating 'type variables' which can be used to create classes, functions & type aliases that don't need to explicitly define the types that they use. Generics makes it easier to write reusable code.


2 Answers

You need to use reflection for this.

var method =
    typeof(MetaDataUtil)
    .GetMethod("GetColumnasGrid")
    .MakeGenericMethod(new [] { type })
    .Invoke(null, null);
like image 127
Derek Slager Avatar answered Oct 05 '22 00:10

Derek Slager


If it is an instance method instead of a static method, then you pass the variable to Invoke(the second parameter null is for an array of parameters that you would usually pass to the method, in the case of null is like calling a method with no parameters .GetColumnAsGrid()):

Type genericTypeParameter = Type.GetType(string.Format("Gestor.Data.Entities.{0}, Gestor.Data", e.Item.Value));
MetaDataUtil someInstance = new MetaDataUtil();

var returnResult =
    typeof(MetaDataUtil)
    .GetMethod("GetColumnsAsGrid")
    .MakeGenericMethod(new [] { genericTypeParameter })
    .Invoke(someInstance, null);//passing someInstance here because we want to call someInstance.GetColumnsAsGrid<...>()

If you have ambiguous overload exception it's probably because GetMethod found more than one method with that name. In which case you can instead use GetMethods and use criteria to filter down to the method you want. This can be kind of fragile though because someone might add another method similar enough to your criteria that it then breaks your code when it returns multiple methods:

var returnResult = 
    typeof(MetaDataUtil)
    .GetMethods().Single( m=> m.Name == "GetColumnsAsGrid" && m.IsGenericMethod 
        && m.GetParameters().Count() == 0 //the overload that takes 0 parameters i.e. SomeMethod()
        && m.GetGenericArguments().Count() == 1 //the overload like SomeMethod<OnlyOneGenericParam>()
    )
    .MakeGenericMethod(new [] { genericTypeParameter })
    .Invoke(someInstance, null);

This isn't perfect because you could still have some ambiguity. I'm only checking the count and you'd really need to iterate through the GetParameters and GetGenericArguments and check each one to make sure it matches the signature that you want.

like image 22
AaronLS Avatar answered Oct 05 '22 02:10

AaronLS