views:

304

answers:

3

Hello, 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?

+4  A: 

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))
}
Lee
Thanks for the reply, I never quite considered such a simple design change.
VoiDeD
+3  A: 

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);
Reed Copsey
Thanks again Reed, your help is very much appreciated.
VoiDeD
+1  A: 

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.

Nick
True, Lee's method would also be better performance-wise, as the additional reflection to retrieve the MethodInfo would be additional computation that could be avoided with his method.
VoiDeD