[C#]反射的实战应用,实际数据模拟
long? value = null;
// 看它是不是 HEX_STRING
var dtAttr = prop.GetCustomAttribute<DataTypeAttribute>();
if (dtAttr != null && dtAttr.DataType == DataType.HEX_STRING)
{// 去掉可能的 "0x" 前缀string txt = attribute.Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)? attribute.Value.Substring(2): attribute.Value;// 按十六进制解析if (long.TryParse(txt, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long hexResult))value = hexResult;
}
else
{// 按十进制解析if (long.TryParse(attribute.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long decResult))value = decResult;
}
- 遍历 XML 里每个属性(XAttribute),
- 反射 找到同名的 GlobalParameter属性 (PropertyInfo),
- 根据那个属性上有没有标记 [DataType(DataType.HEX_STRING)]来决定“按十六进制”还是“按十进制”解析它的字符串值,
- 最后用 prop.SetValue(...)把解析出来的long?写回到globalParameter对象里。
关键解析
var prop = type.GetProperty(attribute.Name.LocalName);
if (prop == null || !prop.CanWrite)continue;
-  type是typeof(GlobalParameter),attribute.Name.LocalName比如"P00A"、"P100"……
-  GetProperty("P00A")就拿到GlobalParameter.P00A的PropertyInfo。
-  prop.CanWrite确保它有公开的 setter,否则无需赋值。
-  GetCustomAttribute<DataTypeAttribute>()读出你在属性上贴的[DataType(DataType.HEX_STRING)]。
-  如果它是 HEX_STRING,就把字符串(可能以"0x"开头)切掉前缀,再用NumberStyles.HexNumber按 16 进制转成long;
-  否则直接按 10 进制 NumberStyles.Integer转。
prop.SetValue(globalParameter, value);
pnNotExists = false;
- 这一行最关键:等同于 动态执行 globalParameter.P00A = value;或globalParameter.P100 = value;
- .NET 在后台会调用对应属性的 set方法,把刚刚解析好的long?写进去。
举例模拟
假设 XML 节点是:
<GlobalParameterP00A="0x000B"P100="2500"
/>
-  第一次循环 - attribute.Name = "P00A",- attribute.Value = "0x000B"
- prop对应- GlobalParameter.Pn00A,它有- [DataType(HEX_STRING)]
- 去前缀后 txt = "000B",TryParse(..., HexNumber)➔hexResult = 11
- prop.SetValue(globalParameter, 11)—— 相当于- globalParameter.P00A = 11;
 
-  第二次循环 - attribute.Name = "Pn100",- attribute.Value = "2500"
- prop对应- GlobalParameter.P100,默认是- INT
- TryParse("2500", Integer)➔- decResult = 2500
- prop.SetValue(globalParameter, 2500)—— 相当于- globalParameter.P100 = 2500;
 
最后返回的 globalParameter 对象里,
globalParameter.P00A == 11;   // 0x000B → 11
globalParameter.P100 == 2500; // 2500
正因为 SetValue 就是调用属性的 setter,所以新解析出来的值就“自动”存到那个实例里了。
