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,默认是INTTryParse("2500", Integer)➔decResult = 2500prop.SetValue(globalParameter, 2500)------ 相当于globalParameter.P100 = 2500;
最后返回的 globalParameter 对象里,
csharp
globalParameter.P00A == 11; // 0x000B → 11
globalParameter.P100 == 2500; // 2500
正因为 SetValue 就是调用属性的 setter,所以新解析出来的值就"自动"存到那个实例里了。