[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,所以新解析出来的值就“自动”存到那个实例里了。