【问题标题】:C# casting the result of GetValue from PropertyInfo to a generic listC# 将 GetValue 的结果从 PropertyInfo 转换为通用列表
【发布时间】:2014-05-04 23:35:34
【问题描述】:

我正在尝试构建一个应用程序,其中类的属性是根据 som XML 文件中的值设置的。
一些类具有由其子项列表组成的属性。由于我制作这个程序的方式,必须通过 propertyinfo 类设置属性。我的问题是我无法获取子列表(Derived2 中的 ICollection)。
它必须转换为通用列表(ICollectionHashSet),因此我不必在每个派生类中复制粘贴相同的 setChild 方法。 我已经尝试将 GetValue 返回值转换为 ICollectionHashSetIENumerable,但没有任何效果。
也许解决方案是使用 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);
        }
    }
}

【问题讨论】:

    标签: c# covariance contravariance propertyinfo


    【解决方案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&lt;T&gt;ICollection&lt;T&gt;,但 ICollection&lt;T&gt; 不是 HashSet。例如,您希望在这种情况下发生什么:

      var list = new List<int>();
      var collection = list as ICollection<int>; // okey
      var set = collection as HashSet<int>; // null
      

    但这不是唯一的问题,因为ICollection&lt;T&gt; 不是协变的。此外,您甚至不需要使用 as 运算符,只需获取值并设置它即可。

    事实上,您甚至不需要获取您的财产的价值。如果您仔细观察它,您将获得您的parent 的财产价值。然后尝试将该值设置回parent。即使可行,也不会改变。您需要:

    p.SetValue(parent, children);
    

    【讨论】:

    • 我让我复制和粘贴错误,该属性应命名为与集合保存的值相同。请查看已编辑的帖子以获取正确的程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2018-02-04
    相关资源
    最近更新 更多