c# - 如何使用反射将未知属性正确地转换为从公共(public)基础派生的通用列表?

标签 c# list generics reflection casting

假设我有以下内容:

public class MyContainer
{
    public string ContainerName { get; set; }
    public IList<Square> MySquares { get; set; }
    public IList<Circle> MyCircles { get; set; }
    public MyContainer()
    {
        MySquares = new List<Square>();
        MyCircles = new List<Circle>();
    }
}

public class Shape
{
    public int Area { get; set; }
}

public class Square : Shape
{
}

public class Circle : Shape
{
}

现在我有一个这样的函数:

private static void Collect(MyContainer container)
{
    var properties = container.GetType().GetProperties();
    foreach (var property in properties)
    {
        if (property.PropertyType.IsGenericType &&
            property.PropertyType.GetGenericTypeDefinition() == typeof(IList<>) &&
            typeof(Shape).IsAssignableFrom(property.PropertyType.GetGenericArguments()[0]))
        {
            var t = property.GetValue(container, null) as List<Square>;
            if (t != null)
            {
                foreach (Shape shape in t)
                {
                    Console.WriteLine(shape.Area);
                }
            }
        }
    }

当我到达 MySquares 属性时,这按照我想要的方式工作,但是我希望改为使用以下方式:

var t = property.GetValue(container, null) as List<Shape>;

我希望它能循环遍历所有具有相似列表的 MyContainer 属性。我有什么办法可以做到这一点吗?

最佳答案

正如我在评论中所建议的那样,使用协变接口(interface)可以实现这一点。

协变/逆变:http://msdn.microsoft.com/en-us/library/ee207183.aspx
另请参阅:Covariance and IList

工作样本

namespace Covariance
{
    public class MyContainer
    {
        public string ContainerName { get; set; }
        public IList<Square> MySquares { get; set; }
        public IList<Circle> MyCircles { get; set; }
        public MyContainer() {
            MySquares = new List<Square>();
            MyCircles = new List<Circle>();
        }
    }

    public class Shape
    {
        public int Area { get; set; }
    }

    public class Square : Shape
    {
    }

    public class Circle : Shape
    {
    }   

    class Program
    {
        static void Main( string[] args ) {

            MyContainer mc = new MyContainer();
            mc.MyCircles.Add( new Circle { Area = 60 } );

            Collect( mc );
            Console.ReadLine();
        }

        private static void Collect( MyContainer container ) {
            var properties = container.GetType().GetProperties();
            foreach( var property in properties ) {
                if( property.PropertyType.IsGenericType &&
                    property.PropertyType.GetGenericTypeDefinition() == typeof( IList<> ) &&
                    typeof( Shape ).IsAssignableFrom( property.PropertyType.GetGenericArguments()[0] ) ) {
                    var t = property.GetValue( container, null ) as IEnumerable<Shape>;
                    if( t != null ) {
                        foreach( Shape shape in t ) {
                            Console.WriteLine( shape.Area );
                        }
                    }
                }
            }
        }
    }
}

关于c# - 如何使用反射将未知属性正确地转换为从公共(public)基础派生的通用列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11787972/

相关文章:

java - 如何获取泛型类型参数?

c# - 是否有允许多个键的 Dictionary<string, object> 集合?

c++ - 表初始化列表取 int,在用户定义的类中

c# - 运算符 '??' 不能应用于类型 'int' 和 'int' 的操作数

python - 将 float 附加到日期列表

python - 如何有条件地从元组列表中删除元素?

java - 为什么在 Java 中使用泛型?它与重载有何不同?

generics - 如何限制 Rust 中特征的通用实现?

c# - 如何强制winCE启动后看到SD/MMC卡

c# - Pin 支付 API - "Authentication failed because remote party has closed the transport stream"