csharp
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
对象里。
关键解析
csharp
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
转。
csharp
prop.SetValue(globalParameter, value);
pnNotExists = false;
- 这一行最关键:等同于 动态执行
globalParameter.P00A = value;
或globalParameter.P100 = value;
- .NET 在后台会调用对应属性的
set
方法,把刚刚解析好的long?
写进去。
举例模拟
假设 XML 节点是:
xml
<GlobalParameter
P00A="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
对象里,
csharp
globalParameter.P00A == 11; // 0x000B → 11
globalParameter.P100 == 2500; // 2500
正因为 SetValue
就是调用属性的 setter,所以新解析出来的值就"自动"存到那个实例里了。