C#将PropertyInfo中GetValue的结果转换为通用列表

时间:2014-05-04 23:35:35

标签: c# covariance contravariance propertyinfo

我正在尝试构建一个应用程序,其中基于som XML文件中的值设置类的属性 有些类具有包含其子项列表的属性。由于我制作这个程序的方式,必须通过propertyinfo类设置属性。我的问题是我在获取子列表时遇到问题( Derived2 中的ICollection)。
它必须强制转换为通用列表( ICollection OR HashSet ),因此我不必在每个派生类中复制粘贴相同的setChild方法。 我已经尝试将 GetValue 返回值转换为 ICollection HashSet IENumerable ,没有效果。
也许解决方案可能是使用 PropertyInfo 类的另一种方法?
一个简化的代码示例代码:

public interface Superclass
{}

public class Derived1 : Superclass {}

public class Derived2 : Superclass
{
    public Derived2()
    {
        PatientForloeb = new HashSet<Derived1>();
    }
    public virtual ICollection<Derived1>Derived1{ get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<Derived1> children = new List<Derived1>();
        children.Add(new Derived1());

        var parent = new Derived2();
        setChild(parent, children);
    }

    private static void setChild(Superclass parent, List<Derived1> children)
    {
        foreach (var child in children)
        {
            var p = (parent.GetType().GetProperty(child.GetType().Name)); // This is ugly, should be based on type not name, but it works for my app.
            var pi = p.GetValue(parent) as HashSet<Superclass>; ///////////<-------This gives null. This is the problem.
            pi.add(child);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

  1. Superclass没有属性,因此实际上p null
  2. 您的媒体资源名称为PatientForloeb而不是Derived1,也许您正在寻找此资源?

    var p = parent
            .GetType()
            .GetProperties()
            .First(x => x.PropertyType.GetGenericArguments()[0] == children.GetType().GetGenericArguments()[0]); 
    
  3. HashSet<T>ICollection<T>ICollection<T>不是HashSet。例如,您希望在这种情况下会发生什么:

    var list = new List<int>();
    var collection = list as ICollection<int>; // okey
    var set = collection as HashSet<int>; // null
    
  4. 但这不是唯一的问题,因为ICollection<T>不是协变。此外,您甚至不需要使用as运算符只需获取值并进行设置。

    事实上,你甚至不需要获得你的财产的价值。如果你仔细看 ,你就会获得parent财产的价值。然后试图将该值设置回parent。即使有效,也不会有任何改变。您需要:

    p.SetValue(parent, children);