Search code examples
c#.netgenericstypesfactory-pattern

Passing variable type to recursive factory as generic


I am trying to write my own factory method for educational purposes when I bumped into the following issue; when trying to call my function recursively, I cant pass a specified type to the generic receptor.

Note: this may have nothing to do with the design pattern at all, this may just be something basic I am doing wrong. Either way, I am a bit stumped.

public static T SpawnObject<T>()
{ 
    var objType = typeof(T);
    var parameters = objType.GetConstructors().Single().GetParameters();
    List<object> paramObjects;

    if (!parameters.Any()) return (T)Activator.CreateInstance(objType);

    paramObjects = new List<object>();
    foreach (var item in parameters)
    {
        //var arg = Activator.CreateInstance(item.ParameterType);
        var paramType = item.ParameterType;
        var arg = SpawnObject<paramType>(); // UNABLE TO ID 'PARAMTYPE' ??
        paramObjects.Add(arg);
    }

    T returnInstance = (T)Activator.CreateInstance(objType, paramObjects.ToArray());
    return returnInstance;
}

Thanks in advance to anyone that can help me understand why this is failing.


Solution

  • See the question I linked above why you can't use a variable as type parameter.

    Here's a simple solution:

    public static T SpawnObject<T>()
    {
        return (T)SpawnObject(typeof(T));
    }
    
    private static object SpawnObject(Type objType)
    {
        var parameters = objType.GetConstructors().Single().GetParameters();
        List<object> paramObjects;
    
        if (!parameters.Any()) return Activator.CreateInstance(objType);
    
        paramObjects = new List<object>();
        foreach (var item in parameters)
        {
            //var arg = Activator.CreateInstance(item.ParameterType);
            var paramType = item.ParameterType;
            var arg = SpawnObject(paramType);
            paramObjects.Add(arg);
        }
    
        return Activator.CreateInstance(objType, paramObjects.ToArray());
    }