C#使用reflection开发.Net3.5来获取/设置嵌套属性和/或嵌套字段的值

我正在开发一个适用于从基类inheritance的数据块类的应用程序,我正在尝试使用Reflection深入到我的数据块类中的属性/字段。 由于所有数据块类都是从基类派生/inheritance的(包含Size属性),我可以使用类型基类的通用变量来轻松地在我的应用程序中创建一个对象; 我也可以在顶层获得/设置属性。 我的问题发生在属性是一个字段时 – 我不知道如何进入字段中的下一级别以获取基本属性和/或字段(如果适用)。

我的基础类:

namespace MyBase { public class BaseClass { private int _size; public BaseClass() { } public BaseClass(int size) { _size = size; } public int Size() { return _size; } } } 

数据块类#1:

 namespace DataBlock_class { //Data block class #1: (contains simple properties - will be used later) public class RecordBlock1_class : MyBase.BaseClass { public byte Char { get; set; } public byte Color { get; set; } public RecordBlock1_class() : base(2) { Char = 0; Color = 0; } } //Data block class #2: (contains simple properties) public RecordBlock2_class : MyBase.BaseClass { public bool Boolean1 { get; set; } public byte Byte1 { get; set; } public short Short1 { get; set; } public ushort UShort1 { get; set; } public RecordBlock2_class() : base(11) { Boolean1 = false; Byte1 = 0; Short1 = 0; UShort1 = 0; } } //Data block class #3: (contains simple properties & fields) public RecordBlock3_class : MyBase.BaseClass { public int Int1 { get; set; } public uint UInt1 { get; set; } public RecordBlock1_class[] ArrayField1 { get; set; } // array of 12 public RecordBlock1_class[] ArrayField2 { get; set; } // array of 12 public RecordBlock1_class[] ArrayField3 { get; set; } // array of 12 public RecordBlock2_class() : base(34) { Int1 = 0; UInt1 = 0; ArrayField1 = new RecordBlock1_class[12]; for(int x = 0; x < 12; x++) { ArrayField1[x] = new RecordBlock1_class(); } ArrayField2 = new RecordBlock1_class[12]; for(int x = 0; x < 12; x++) { ArrayField2[x] = new RecordBlock1_class(); } ArrayField3 = new RecordBlock1_class[12]; for(int x = 0; x < 12; x++) { ArrayField3[x] = new RecordBlock1_class(); } } } } 

由于我的所有数据块类都是从MyBase.BaseClass派生/inheritance的,所以我可以将它用于我的变量 – 我不会在运行时处理哪种类型的数据块类。

在我的C#app中,我有以下代码块:

 string CSharpQualifiedName = ""; // DataBlock_class.RecordBlock1_class // DataBlock_class.RecordBlock2_class // DataBlock_class.RecordBlock3_class 

使用我的MyBase.BaseClass变量,然后我可以实例化一个MyBase.BaseClass对象:

 MyBase.BaseClass baseClass = null; Type baseClassType = Type.GetType(CSharpQualifiedName); if(baseClassType == null) { foreach(Assembly asm in AppDomain.CurrentDomain.GetAsseblies()) { baseClassType= asm.GetType(CSharpQualifiedName); if(baseClassType != null) { baseClass = Activator.CreateInstance(baseClassType) as MyBase.BaseClass; break; } } } 

处理前两个数据块类很容易 – 我可以使用PropertyInfo来获取/设置值。

 string fieldProperty = ""; PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty); 

现在,我的proplem /问题是RecordBlock3_class – 如何到达任何数组字段/属性中的一个项目然后到RecordBlock1_class中的Char / Color属性?

我可以使用FieldInto来访问ArrayFieldX字段,但之后我迷路了?

 FieldInfo fi = baseClass.GetType().GetField(fieldProperty); 

任何帮助/建议都非常有用!! 我还要说一点,当用户创建更多嵌套类结构时,数据块类会变得更复杂一些。

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

 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"); 

当然这两种方法都需要对error handling等进行一些抛光