Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a generic function with a type parameter determined at runtime

I have a question involving calling a class's generic method with a type parameter that is known at runtime.

In specific, the code looks like so:


FieldInfo[] dataFields = this.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance );

// data is just a byte array used internally in DataStream
DataStream ds = new DataStream( data );

foreach ( FieldInfo field in dataFields )
{
    Type fieldType = field.FieldType;

    // I want to call this method and pass in the type parameter specified by the field's type
    object objData = ( object ) ds.Read<fieldType>();
}

The Read() function looks like so:


public T Read() where T : struct

This function's purpose is to return data read from a byte array.

Is there any way to call a generic method at runtime like this?

like image 290
Ryan Stecker Avatar asked Sep 21 '09 18:09

Ryan Stecker


3 Answers

The easiest way to handle this would be to make a non-generic overload of the Read function with a single Type parameter:

public object Read(Type t)

And then have the generic version call the non-generic version:

public T Read<T>() where T : struct
{
    return (T)Read(typeof(T))
}
like image 84
Lee Avatar answered Oct 13 '22 19:10

Lee


You'll need to build a methodinfo and invoke the Read method:

MethodInfo method = typeof(DataStream).GetMethod("Read");
MethodInfo generic = method.MakeGenericMethod(fieldType);
object objData = generic.Invoke(ds, null);
like image 41
Reed Copsey Avatar answered Oct 13 '22 19:10

Reed Copsey


It would probably be better to go Lee's route. Generic's are shorthand at design-time to keep you from having to write common code for many different types of classes. At compile time every call to a generic method or class is basically generated as a completely separate class.

Much simpler to just bass the the type and use reflection, which is what you would have to do anyways.

like image 34
Nick Avatar answered Oct 13 '22 21:10

Nick