在运行时创建通用对象列表

时间:2016-12-06 08:26:44

标签: c# generics

我有一些在运行时已知的类型的对象,我从数据库中读取和反序列化此对象。有用。现在我想将它添加到一些列表中:

private static List<T> generateList<T>()
{
    List<T> lst = new List<T>();
    return lst;
}

private void readObjects(System.Type objType)
{
    var methodInfo = typeof(My.Serializator).GetMethod("DeserializeDb");
    var genericMethod = methodInfo.MakeGenericMethod(objType1);
    List<curType> currentList= generateList<curType>();
    // ...read stream from database and convert it to object
    while (_rs.Read())
    {
        var _objItem = genericMethod.Invoke(null, new[] { _streamedData });
        currentList.Add(_objItem);
    }
}

它无效。错误是:

  

curType是一个变量,但用作类型。

如果我将列表更改为:

 List<object> currentList = new List<object>(); 

它会起作用。但我可以用泛型(T)代替对象类型吗?

1 个答案:

答案 0 :(得分:1)

您可以通过Activator轻松创建所需的列表类型,然后转换为IList并使用它:

private IList readObjects(System.Type objType)
{
    var listType = typeof(List<>).MakeGenericType(curType);
    var list = (IList)Activator.CreateInstance(listType);

    // ...

    while (_rs.Read())
    {
        // ...
        list.Add(_objItem);
    }
}

list将是List<YorActualType>的实例。

更新

当您使用泛型参数声明方法时,它假定您在编译期间提供类型信息。否则你需要使用反射。

由于您在运行时提供类型信息(curType可以保存任何类型信息),编译器不知道将使用什么样的类型,并且您不能声明您的方法返回具体的东西。只允许抽象。

让我用稍微疯狂但有示范性的例子来表明:

var types = new [] { typeof(int), typeof(string) };
var rand = new Random();
var list = readObjects(types[rand.Next(0,2)];

直到最后一刻,即使你不知道究竟会创建什么类型的列表。编译器也不知道。如果您没有向他提供类型,编译器将永远不知道应该使用什么类型。当您使用Type时,它只告诉编译器一些类型为Type的常规参数将在运行时传递给该方法。在编译期间没有数据可以推断出类型。该数据只能通过generic type parameters传递。

因此,有几种方法可以遵循:

  1. 在编译时提供您需要的确切类型

    private List<T> readObjects<T>()
    {
        var objType = typeof(T);
        var list = new List<T>();
        // rest of code....
    }
    
  2. 使用反射和基本类型

    private IList readObjects(Type objType)
    {
        // rest of code with Activator and so on
    }
    

    以后的使用取决于您的需求。 如果您知道要使用的类型,只需转换:

    var list = (IList<MyType>)readObjects(typeof(myType));
    

    但我认为在这种情况下更好地使用#1和泛型参数。

    否则你将使用反射。或者一些基类,接口等。这取决于你要解决的具体任务。

  3. P.S。您可以在MSDN上阅读有关generic types的更多信息。