繁体   English   中英

包含c#中列表的动态类型

[英]Dynamic type with lists in c#

我有一点问题。

我想这样做:

Type[] classes = new Type[]{ Class1, Class2 };

foreach(Type t in classes){   
  List<t> list = new List<t>(); 
}

有办法做到这一点吗?

不能在运行时转换为泛型类型,因为泛型中的类型需要在编译时解析。

可以使用反射以动态方式创建泛型类型,但除非您对强制转换进行硬编码,否则您获得的所有内容都是对象。

我不能真正说出你想要的是什么,我不得不同意这是一个XY问题 我倾向于做出这样一种冒昧的陈述:这是一个设计问题,它试图解决,而不是直接解决设计问题,或者询问你想要直接实现的问题。


您可以使用以下代码创建类型,然后dynamic类型可用于在不知道/关心它是列表或T是什么的情况下对List<T>的各种成员进行类型化

using System;
using System.Collections.Generic;

namespace ConsoleApplication61
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic o = CreateGeneric(typeof(List<>), typeof(int));
            o.Add(1);
            Console.WriteLine(o[0]);
            Console.Read();
        }

        public static object CreateGeneric(Type generic, Type innerType, params object[] args)
        {
            System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
            return Activator.CreateInstance(specificType, args);
        }
    }
}

上面的示例duck类型是Add方法和Indexer。 DLR在运行时执行类型处理和鸭子类型 - 例如,知道1int

只是为了澄清,我可能不会在生产中使用这样的代码(除非你的要求非常具体需要这个),并且任何类型不匹配的问题都会在运行时发生; 因此您需要非常准确地键入(有限的IntelliSense)或具有良好的错误处理。

感谢这篇关于CreateGeneric方法的博客文章

这假定.NET 4具有新的CLR。 正如@MartinLiversage也指出的那样,这个特定的示例假设您以强类型的方式使用列表。 在我的例子中,我将一个int传递给dynamic隐藏的List<int>


自从它发布以来,我们一直在使用.NET 4。 我们有一个大型应用程序,具有更大的代码库。 dynamic在应用程序中不使用一次,在测试代码库中只使用几次。 这并不是说“不要使用它”,而是说“大多数时候,你不需要它”。

你可以这样做:

foreach(Type t in classes)
{
   var listType = typeof(List<>).MakeGenericType(t);
   var instance = Activator.CreateInstance(listType);
}

这可以使用Type.MakeGenericType方法

这是一个我发现应该适用于ya的漂亮方法: CodeRef

public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
    System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
    return Activator.CreateInstance(specificType, args);
}

并像这样使用它:

var o = CreateGeneric(typeof(List<>), t);

不幸的是,要添加项目,您必须这样做(其中item是您要添加的项目)。

MethodInfo addMethod = o.GetType().GetMethod("Add");
addMethod.Invoke(o, new object[] { item.ToType(t) });

或者使用另一个答案中提到的Generic类型。

你可以试试这个:

Type[] classes = new Type[] { typeof(A), typeof(B) };           
foreach (Type t in classes)
{
     Type genericType = typeof(List<>).MakeGenericType(t);
     var list = Activator.CreateInstance(genericType);
}

如果你想在一个列表中保留对象,那么它们可能有一些共同之处。

在这种情况下,我认为,就像评论中提到的LB一样,你在这里提出了一个错误的问题。

可能这是你的设计问题。 考虑一下这些类型,看看它们有什么共同点,并考虑从一种基本类型派生,或者两者都实现相同的接口。 在这种情况下,您将能够实例化基本类型/接口的对象列表并使用它们。

只是为了给你一个良好的开端:

    abstract class Vehicle {
        public int NumberOfWheels { get; set; }
    }

    class Car : Vehicle
    {
        public Car()
        {
            NumberOfWheels = 4;
        }
    }

    class Bicycle : Vehicle
    {
        public Bicycle()
        {
            NumberOfWheels = 2;
        }
    }

    static void Main(string[] args)
    {

        var v1 = new Car();
        var v2 = new Bicycle();

        var list = new List<Vehicle>();
        list.Add(v1);
        list.Add(v2);

        foreach (var v in list)
        {
            Console.WriteLine(v.NumberOfWheels);
        }

        Console.ReadKey();
    }

暂无
暂无

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

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