简体   繁体   English

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

[英]Create list of generic object at runtime

I have object of some type known at runtime and I read and deserialize this object from database. 我有一些在运行时已知的类型的对象,我从数据库中读取和反序列化此对象。 It works. 有用。 Now I would like to add it to some list: 现在我想将它添加到一些列表中:

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);
    }
}

It won't work. 它不会起作用。 The error is: 错误是:

curType is a variable but is used like a type. curType是一个变量,但是像类型一样使用。

If I change list to: 如果我将列表更改为:

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

it will work. 它会工作。 But can i do this with generics(T) instead of object type? 但我能用泛型(T)代替对象类型吗?

You can easly create type of list you want via Activator , then cast to IList and use it: 您可以通过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 will be instance of List<YorActualType> . list将是List<YorActualType>实例。

Update 更新

When you declaring your method with generic arguments, it assumes you provide type info during compile time. 当您使用泛型参数声明方法时,它假定您在编译期间提供类型信息。 Otherwise you need to use reflection. 否则你需要使用反射。

Since you providing type info in run time ( curType can hold any type info), compiler does not know what exactly type will be used, and you cannot declare your method to return something concrete. 由于您在运行时提供类型信息( curType可以包含任何类型信息),编译器不知道将使用什么样的类型,并且您不能声明您的方法返回具体的东西。 Only abstractions allowed. 只允许抽象。

Let's me show it on slightly insane but demonstrative example: 让我用稍微疯狂但示范性的例子来展示它:

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

Until the very last moment even you will not know what exactly type of list will be created. 直到最后一刻,即使你不知道究竟会创建什么类型的列表。 Compiler does not know too. 编译器也不知道。 Compiler will never know what exactly type should be used if you not provide him with you types. 如果您没有向他提供类型,编译器将永远不知道应该使用什么类型。 When you use Type it only tells compiler that some regular parameter with type Type will be passed into the method in run time. 当你使用Type ,它只告诉编译器一些类型为Type常规参数将在运行时传递给方法。 There is no data to infer a type during compile time. 在编译期间没有数据可以推断出类型。 That data can be passed only via generic type parameters . 该数据只能通过泛型类型参数传递。

So, there is several ways you can follow: 因此,有几种方法可以遵循:

  1. Provide exact types you need at compile time 在编译时提供所需的确切类型

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

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

    And later usage depends on your needs. 以后的使用取决于您的需求。 If you know what type you going to use, simply convert: 如果您知道要使用的类型,只需转换:

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

    But I guess in that case better use way #1 with generic argument. 但我想在这种情况下更好地使用方式#1与泛型参数。

    Otherwise you going to use reflection. 否则你将使用反射。 Or some base classes, interfaces and so on. 或者一些基类,接口等。 It depends on what exactly task you going to solve. 这取决于你要解决的具体任务。

PS You can read more about generic types on MSDN. PS您可以在MSDN上阅读有关泛型类型的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM