从对象子级获取特定属性

时间:2014-04-28 13:11:41

标签: c# reflection

挣扎着提出一个体面的方式来提问/标题这个问题,但我会尽力说明它。

我正在使用类似这样的数据结构:

public Foo
{
     public Bar Bar {get;set;}
}

public Bar
{
    public SubTypeA TypeA {get;set;}
    public SubTypeB TypeB {get;set;}
    ...
}

public SubTypeA
{
    public int Status {get;set;}
    ...
}

请注意,我无法更改此数据结构。

Bar类中有许多不同的类型,它们都具有不同的属性,但所有类型共有的是Status的属性。

我需要做的是,给出一个Foo类型的对象,记录其中Bar个对象中每个项目的状态。并非每个SubType每次都会有一个值,有些可能为空。

我可以使用下面的递归函数来管理它,以遍历所有属性。虽然我不认为循环可能会变得很大,因为每个SubType上可能有很多属性,但这并不理想。

private void GetProperties(Type classType, object instance)
{
    foreach (PropertyInfo property in classType.GetProperties())
    {

        object value = property.GetValue(instance, null);
        if (value != null) 
        {
            if (property.Name == "Status")
            {
                Record(classType, value);
            }
            GetProperties(property.PropertyType, value);
        }
    }
}

这是关于这种问题的唯一方法吗?

编辑:按照Selman22给出的答案,我提出了另一个问题,其中我试图根据对象的状态和名称创建一个匿名对象。

var z = instance.GetType()
            .GetProperties()
            .Select(x => new 
                { 
                    status = x.GetValue(instance).GetType().GetProperty("status").GetValue(x, null), 
                    name = x.Name 
                })
            .ToList();

尝试检索值时,会抛出Object does not match target type.错误。这可能是1个班轮吗?

2 个答案:

答案 0 :(得分:1)

类型类包含可用于检索特定属性的 GetProperty(字符串名称,BindingFlags方法)。而不是遍历每个属性使用此方法。

http://msdn.microsoft.com/en-us/library/system.type.getproperty(v=vs.110).aspx

// Get Type object of MyClass.
Type myType=typeof(MyClass);       
// Get the PropertyInfo by passing the property name and specifying the BindingFlags.
PropertyInfo myPropInfo = myType.GetProperty("MyProperty", BindingFlags.Public | BindingFlags.Instance);

答案 1 :(得分:0)

您可以使用Status而不是递归来获取所有LINQ属性:

var barInstance = typeof(Foo).GetProperty("Bar").GetValue(fooInstance);

var statusProperties = barInstance.GetType()
            .GetProperties()
            .Select(x => x.GetValue(barInstance).GetType().GetProperty("Status"));