How to pass a dynamic model as 'T' to a C# generic function

Viewed 2758

I have a generic function which is like below

private List<T> GetAll<T>()
{
    var listOfTModels = // gets the list of T from the database.

    return listOfTModels;
}

I need to pass the model ( T ) dynamically to this function based on a string which will be decided at runtime.

public void SomeFunction(string modelName)
{
     // Call the above Get method with modelName parameter as the 'T'

     var listOfModels = GetAll<something>(); //not sure what type this something should be "Type" or "string"

     // Further Logic on listOfModels
}

How could this be done?

2 Answers

You will need to use reflection to get the method like so:

typeof(ClassWithGetAll).GetMethod("GetAll",
                       BindingFlags.Instance | BindingFlags.NonPublic);

This will return a method info which you will then use to create a generic method via MakeGenericMethod.

The only way to get a type from a string name AFAIK is with Type.GetType but you will need a AssemblyQualifiedName for that, so passing in a short/simplified name like string or int or anything like that will more than likely return null.

If you figure out how to either get the qualified name or how to search for the type, the last thing would be to invoke the MethodInfo returned from the MakeGenericMethod call, here is a example of how the code could look:

public void SomeFunction(string modelName)
{
    // No idea what the class/struct in which the method "GetAll" 
   // is called, hence use this name
    var instance = new ClassWithGetAll();

    //Retrieves the info of "GetAll<T>"
    MethodInfo method = typeof(ClassWithGetAll).GetMethod("GetAll", 
                        BindingFlags.Instance | BindingFlags.NonPublic);

    //Commented out as you will need to figure out how to get the 
    // assembly qualified name of the input model name, unless 
    // it is qualified.
    //modelName = GetAssemblyQualifiedName(modelName);

    Type modelType = Type.GetType(modelName);

    //Creates a generic method: "GetAll<T>" => "GetAll<modelType>"
    method = method.MakeGenericMethod(modelType);

    //Invokes the newly created generic method in the specified 
    // instance with null parameters, which returns List<modelType>
    object list = method.Invoke(instance, null);
}

I think inheritance would be the right way to solve your problem.

public class TBase
{
    public int Prop { get; set; }
}
public class TChildOne : TBase
{

}
public class TChildTwo : TBase
{

}

public class GClass
{
    private List<T> GetAll<T>() where T : TBase
    {
        var listOfTModels = // gets the list of T from the database.
        return listOfTModels;
      }


    public void Main(string strType)
    {
        switch (strType)
        {
            case "TChildOne":
                {
                    var child = GetAll<TChildOne>();
                    break;
                }
            case "TChildTwo":
                {
                    var child = GetAll<TChildTwo>();
                    break;
                }
            default:
                throw new Exception("type not found");
        }

    }
}
Related