My advice is to not go in this direction and if you do pass in a fully qualified class name and work within the method which brings up a sore point of endless use of reflection. Here is a start
/// <summary>
/// Given a fully qualified model/class name create a generic list
/// </summary>
/// <param name="className"></param>
public static void CreateGenericList(string className)
{
var type = Type.GetType(className, true);
var genericListType = typeof(List<>).MakeGenericType(type);
var genericList = Activator.CreateInstance(genericListType);
}
You are better off performing assertion and select a strong typed model and use code like this
public static class Extensions
{
/// <summary>
/// Convert DataTable to List of T
/// </summary>
/// <typeparam name="TSource">Type to return from DataTable</typeparam>
/// <param name="table">DataTable</param>
/// <returns>List of <see cref="TSource"/>Expected type list</returns>
public static List<TSource> DataTableToList<TSource>(this DataTable table) where TSource : new()
{
List<TSource> list = new();
var typeProperties = typeof(TSource).GetProperties().Select(propertyInfo => new
{
PropertyInfo = propertyInfo,
Type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType
}).ToList();
foreach (var row in table.Rows.Cast<DataRow>())
{
TSource current = new();
foreach (var typeProperty in typeProperties)
{
object value = row[typeProperty.PropertyInfo.Name];
object safeValue = value is null || DBNull.Value.Equals(value) ?
null :
Convert.ChangeType(value, typeProperty.Type!);
typeProperty.PropertyInfo.SetValue(current, safeValue, null);
}
list.Add(current);
}
return list;
}
}