C#中使用反射来的get / set值嵌套的性能和/或嵌套领域发展.NET3.5 [英] C# Developing .Net3.5 using reflection to get/set values to nested properties and/or nested fields
问题描述
我正在开发与基类inheritied数据块类工作的应用程序,我试图使用反射来在我的数据块级向下钻取到性能/领域。由于所有的数据块类衍生/从基类(包含一个Size属性)继承我可以使用类的基类的一般变量来很轻松地创建我的应用程序的对象;我还可以得到在顶层/设置属性。当属性是一个场出现我的问题 - 我不知道怎么去一个新的水平在现场如果有去的基本属性和/或字段,
I'm developing an app that works with data block classes inheritied from a base class and I am trying to use Reflection to drill down to properties/fields in my data block class. Since all the data block classes are derived/inherited from the base class (which contains a Size property) I can use a general variable of type base class to create an object in my app easily enough; I can also get/set properties at a top level. My problem occurs when the property is a field - I do not know how to get to the next level in the field to get to the base properties and/or fields, if applicable.
我的BaseClass的:
My BaseClass:
namespace MyBase {
public class BaseClass {
private int _size;
public BaseClass() { }
public BaseClass(int size) {
_size = size;
}
public int Size() {
return _size;
}
}
}
数据块级#1:
Data block class #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我的所有数据块类派生/继承,我可以用这为我的变量 - 我不知道是什么类型的数据块级的,我会在运行时处理
Since all my data block classes derive/inherit from MyBase.BaseClass, I can use this for my variable - I do not what type of data block class I will be processing at run time.
在我的C#应用程序,我有以下代码块:
in my C# app, I have the following block of code:
string CSharpQualifiedName = "<this could be any of the data block classes above>";
// DataBlock_class.RecordBlock1_class
// DataBlock_class.RecordBlock2_class
// DataBlock_class.RecordBlock3_class
使用我的MyBase.BaseClass变量,然后我就可以实例化一个对象MyBase.BaseClass:
Using my MyBase.BaseClass variable, I can then instantiate a MyBase.BaseClass object:
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获取/设定值
Dealing with the first two data block classes are easy enough - I can using PropertyInfo to get/set values.
string fieldProperty = "<any property in the class>";
PropertyInfo pi = baseClass.GetType().GetProperty(fieldProperty);
现在,我proplem /问题是RecordBlock3_class - 如何获取到的项目之一中的任何数组字段/属性,然后在RecordBlock1_class的字符/ Color属性?
Now, my proplem/issue is RecordBlock3_class - How do I get to one of the items in any of array fields/properties AND then to the Char/Color property in RecordBlock1_class???
我可以使用FieldInto才能到ArrayFieldX领域,但我之后失去了什么?
I can use FieldInto to get to the ArrayFieldX fields, but I'm lost after that?
FieldInfo fi = baseClass.GetType().GetField(fieldProperty);
任何帮助/咨询大大appreicated!我会多说一句,数据块类能有点复杂,因为用户创造更多的嵌套类结构。
Any assistance/advice is greatly appreicated!! I will say one more thing, the data block classes can get a bit more complex as users create more nested class structures.
推荐答案
您可以通过反射也是数组属性的元素类型,然后通常会得到它的属性:
You can get element type of the array property by Reflection also, and then get its properties normally:
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");
}
根据这一点,你可以写在中横过嵌套简单而比较通用的功能属性(也使用领域,只需修改下面的代码):
Based on that, you can write simple yet more generic function that is traversing nested properties (to use also fields, simply modify below code):
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;
}
,然后你可以用'路径'查询'的对象:
and then you can 'query' objects with 'paths':
PropertyInfo pi = GetProperty(c1.GetType(), "ArrayField1/Char");
PropertyInfo pi2 = GetProperty(c2.GetType(), "Color");
如果你想获得这样的对象值的方法将是类似的:
If you want to get values of object in this way, a method will be similar:
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;
}
然后你就可以得到价值查询,包括阵列,例如:
And then you can get values queries, including arrays, for example:
var v = GetPropertyValue(baseClass, "ArrayField1[5]/Char");
当然,这两种方法需要错误处理等一些抛光。
Of course both methods requires some polishing of error handling etc.
这篇关于C#中使用反射来的get / set值嵌套的性能和/或嵌套领域发展.NET3.5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!