Matthys Du Toit
Matthys Du Toit

Reputation: 2400

Passing an instance of a dynamic type to a generic method in a generic class

I have a generic class that exposes a generic method. This method receives an instance of the generic object as parameter and modifies this instance.

Example class:

public class GenericClass<T>
{
    public T GenericMethod(T obj)
    {
        // modify the object in some (arbitrary) way
        IEnumerable<FieldInfo> fields = obj.GetType().GetRuntimeFields();
        foreach (FieldInfo field in fields)
        {
            if (field.FieldType == typeof(string))
            {
                field.SetValue(obj, "This field's string value was modified");
            }
        }

        return obj;
    }
}

If I have a type (abc):

public class abc
{
    public string a;
    public string b;
    public int c;
}

I can call this method as follows:

GenericClass<abc> myGeneric = new GenericClass<abc>();
var myObject = myGeneric.GenericMethod(new abc());

//Confirm success by printing one of the fields
Console.Writeline(((abc)myObject).a);

Now, my actual question:

How would I call this same Generic method, using a type that is only known at run-time (as opposed to type abc above). I also want to instantiate this this as I pass it in to the GenericMethod, just like I did for abc above.

E.g. (I know this is completely wrong)

Type MyType;

GenericClass<MyType> myGeneric = new GenericClass<MyType>();
var myObject = myGeneric.GenericMethod(new MyType());

Due to unknown type success cannot be confirmed by printing the field "a" which may not exist, I could print the value of all string fields, but this is beyond the scope of the question.

Upvotes: 1

Views: 7317

Answers (1)

Sebastian Schumann
Sebastian Schumann

Reputation: 3446

To answer your question:

var type = typeof(abc);
object instanceToModify = new abc();

var typeToCreate = typeof(GenericClass<>).MakeGenericType(type);
var methodToCall = typeToCreate.GetMethod("GenericMethod");

var genericClassInstance = Activator.CreateInstance(typeToCreate);
methodToCall.Invoke(genericClassInstance, new[] { instanceToModify });

DEMO

But:

If your type is only known at runtime your instance must be handled in a variable declared as object or dynamic. In that case you can change your method signature to:

public object GenericMethod(object obj)
{
    // modify the object in some (arbitrary) way
    IEnumerable<FieldInfo> fields = obj.GetType().GetRuntimeFields();
    foreach (var field in fields)
    {
        if (field.FieldType == typeof(string))
        {
            field.SetValue(obj, "This field's string value was modified");
        }
    }

    return obj;
}

There's no need for a generic class/method.

Upvotes: 1

Related Questions