Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting generic type at runtime

Tags:

c#

generics

I have a class

public class A<T>
{
   public static string B(T obj)
   {
       return TransformThisObjectToAString(obj);
   }
}

The use of string above is purely exemplary. I can call the static function like this just fine on a known/specified type:

string s= A<KnownType>.B(objectOfKnownType);

How do I make this call, if I don't know T beforehand, rather I have a variable of type Type that holds the type. If I do this:

Type t= typeof(string);
string s= A<t>.B(someStringObject);

I get this compiler error:

Cannot implicitly convert type 't' to 'object'
like image 929
Venkat Peri Avatar asked Apr 09 '10 02:04

Venkat Peri


People also ask

What is generic in runtime?

When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Specialized generic types are created one time for each unique value type that is used as a parameter.

Is generic type information present at runtime?

Generic type information is not present at runtime. C. You cannot create an instance using a generic class type parameter.

How do you create a generic type?

A Generic Version of the Box Class To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.


3 Answers

You can't do this directly, but you can use reflection to provide a type parameter of a class at run-time. I haven't tested this, but something like this should work:

// We want to do something like this: //    object o = "Hello" //    Type t = o.GetType();  // // This is pseudo-code only: //    string s = A<t>.B(o);   string InvokeA(object o) {   // Specify the type parameter of the A<> type   Type genericType = typeof(A<>).MakeGenericType(new Type[] { o.GetType() });   // Get the 'B' method and invoke it:   object res = genericType.GetMethod("B").Invoke(new object[] { o });   // Convert the result to string & return it   return (string)res; } 

Of course, the question is if this is really what you need - If you don't know anything about the object given as an argument, you could as well write the whole code just using object. However, I can imagine some scenarios where this would be useful, so I guess you can try using this.

like image 176
Tomas Petricek Avatar answered Sep 27 '22 15:09

Tomas Petricek


There's absolutely support for this in the framework and the CLR - just not gracefully in C#. You can accomplish what I think you want, though, with the help of a helper method:

public class A<T>
{
    public static string B(T obj)
    {
        return obj.ToString();
    }
}

public class MyClass
{
    public static void DoExample()
    {
        Console.WriteLine(ExecuteB("Hi"));
        Console.WriteLine(ExecuteB(DateTime.Now));
    }

    public static object ExecuteB(object arg)
    {
        Type arg_type = arg.GetType();
        Type class_type = typeof(MyClass);
        MethodInfo mi = class_type.GetMethod("ExecuteBGeneric", BindingFlags.Static | BindingFlags.Public);
        MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { arg_type });
        return mi2.Invoke(null, new object[] { arg });
    }

    public static object ExecuteBGeneric<T>(T arg)
    {
        return A<T>.B(arg);
    }
like image 37
Dathan Avatar answered Sep 27 '22 16:09

Dathan


You can't. Generic type identifiers have to be known at compile time.

edit

as of other posts, it appears to be possible by dynamicly generating the method and invoking it - which has dangers of course. See Thomas' and Dathan's posts for more inforation.

like image 31
Femaref Avatar answered Sep 27 '22 15:09

Femaref