C#正在开发.Net3.5,使用反射获取/设置嵌套属性和/或嵌套字段的值

C#正在开发.Net3.5,使用反射获取/设置嵌套属性和/或嵌套字段的值,c#,inheritance,reflection,propertyinfo,fieldinfo,C#,Inheritance,Reflection,Propertyinfo,Fieldinfo,我正在开发一个应用程序,它可以处理从基类继承的数据块类,我正在尝试使用反射深入到我的数据块类中的属性/字段。由于所有数据块类都是从基类(包含大小属性)派生/继承的,因此我可以使用基类类型的常规变量在我的应用程序中轻松创建对象;我还可以在顶层获取/设置属性。我的问题发生在属性是字段时-我不知道如何进入字段的下一个级别以访问基本属性和/或字段(如果适用) 我的基类: namespace MyBase { public class BaseClass { private int _

我正在开发一个应用程序,它可以处理从基类继承的数据块类,我正在尝试使用反射深入到我的数据块类中的属性/字段。由于所有数据块类都是从基类(包含大小属性)派生/继承的,因此我可以使用基类类型的常规变量在我的应用程序中轻松创建对象;我还可以在顶层获取/设置属性。我的问题发生在属性是字段时-我不知道如何进入字段的下一个级别以访问基本属性和/或字段(如果适用)

我的基类:

namespace MyBase {
   public class BaseClass {
       private int _size;
       public BaseClass() { }
       public BaseClass(int size) {
           _size = size;
       }
       public int Size() {
           return _size; 
       }
   }
}
数据块类#1:

处理前两个数据块类非常简单——我可以使用PropertyInfo获取/设置值

string fieldProperty = "<any property in the class>";
PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty);

非常感谢您的任何帮助/建议!!我还要说一件事,随着用户创建更多的嵌套类结构,数据块类可能会变得更复杂一些

您也可以通过反射获取数组属性的元素类型,然后正常获取其属性:

string fieldProperty = "ArrayField1";
System.Reflection.PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty);
if (pi.PropertyType.IsArray)
{
    Type elementType = pi.PropertyType.GetElementType();
    System.Reflection.PropertyInfo pi2 = elementType.GetProperty("Color");
}
基于此,您可以编写简单但更通用的函数来遍历嵌套属性(要同时使用字段,只需修改以下代码):

如果要以这种方式获取对象的值,将有一种类似的方法:

static object GetPropertyValue(object obj, string propertyPath)
{
    System.Reflection.PropertyInfo result = null;
    string[] pathSteps = propertyPath.Split('/');
    object currentObj = obj;
    for (int i = 0; i < pathSteps.Length; ++i)
    {
        Type currentType = currentObj.GetType();
        string currentPathStep = pathSteps[i];
        var currentPathStepMatches = Regex.Match(currentPathStep, @"(\w+)(?:\[(\d+)\])?");
        result = currentType.GetProperty(currentPathStepMatches.Groups[1].Value);
        if (result.PropertyType.IsArray)
        {
            int index = int.Parse(currentPathStepMatches.Groups[2].Value);
            currentObj = (result.GetValue(currentObj) as Array).GetValue(index);
        }
        else
        {
            currentObj = result.GetValue(currentObj);
        }

    }
    return currentObj;
}

当然,这两种方法都需要对错误处理等进行一些改进。

感谢您的回答-一个问题:当我处理RecordBlock3\u类对象时,如何在ArrayField1[x].Char//之间区分GUI,其中x可以是0。。21???你为什么要这样做?我的意思是——从类型的角度来看,它们都是一样的。例如,ArrayField1[3].Char或ArrayField1[10].Char将提供相同的信息。或者你想使用这些信息来获取这些属性的实际值?我在回答中添加了一种以类似方式获取值的方法;所以ArrayField1将显示12个字符。。。这就是为什么我需要能够单独获取/设置每个。再次感谢您的指导。因此您可以使用上面编写的
GetPropertyValue
获取值并编写相应的setter方法。
string fieldProperty = "<any property in the class>";
PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty);
FieldInfo fi = baseClass.GetType().GetField(fieldProperty);
string fieldProperty = "ArrayField1";
System.Reflection.PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty);
if (pi.PropertyType.IsArray)
{
    Type elementType = pi.PropertyType.GetElementType();
    System.Reflection.PropertyInfo pi2 = elementType.GetProperty("Color");
}
static System.Reflection.PropertyInfo GetProperty(Type type, string propertyPath)
{
    System.Reflection.PropertyInfo result = null;
    string[] pathSteps = propertyPath.Split('/');
    Type currentType = type;
    for (int i = 0; i < pathSteps.Length; ++i)
    {
        string currentPathStep = pathSteps[i];
        result = currentType.GetProperty(currentPathStep);
        if (result.PropertyType.IsArray)
        {
            currentType = result.PropertyType.GetElementType();
        }
        else
        {
            currentType = result.PropertyType;
        }
    }
    return result;
}
PropertyInfo pi = GetProperty(c1.GetType(), "ArrayField1/Char");
PropertyInfo pi2 = GetProperty(c2.GetType(), "Color");
static object GetPropertyValue(object obj, string propertyPath)
{
    System.Reflection.PropertyInfo result = null;
    string[] pathSteps = propertyPath.Split('/');
    object currentObj = obj;
    for (int i = 0; i < pathSteps.Length; ++i)
    {
        Type currentType = currentObj.GetType();
        string currentPathStep = pathSteps[i];
        var currentPathStepMatches = Regex.Match(currentPathStep, @"(\w+)(?:\[(\d+)\])?");
        result = currentType.GetProperty(currentPathStepMatches.Groups[1].Value);
        if (result.PropertyType.IsArray)
        {
            int index = int.Parse(currentPathStepMatches.Groups[2].Value);
            currentObj = (result.GetValue(currentObj) as Array).GetValue(index);
        }
        else
        {
            currentObj = result.GetValue(currentObj);
        }

    }
    return currentObj;
}
var v = GetPropertyValue(baseClass, "ArrayField1[5]/Char");