【发布时间】:2021-05-31 11:48:12
【问题描述】:
在尝试基于 Json 文件设置“复杂”类层次结构时,我遇到了一个问题,这肯定是由于我在反射过程中缺乏知识。
这是我的主要模型:
public class Names
{
public Weapons Weapons { get; set; }
public Armors Armors { get; set; }
public Utilities Utilities { get; set; }
public Names()
{
Weapons = new Weapons();
Armors = new Armors();
Utilities = new Utilities();
}
}
他们每个人都有一个这样的子模型列表:
public class Weapons
{
public BattleAxe BattleAxe { get; set; } = new BattleAxe();
public Bomb_Missile Bomb_Missile { get; set; } = new Bomb_Missile();
// etc... Around 20 to 25
}
最后是最终模型,它与每个 json 文件完全等效,但可能具有非常不同的属性:
public class BattleAxe
{
public string[] Normal { get; set; } = new string[0];
public string[] DescriptiveAdjective { get; set; } = new string[0];
public string[] Material { get; set; } = new string[0];
public string[] Type { get; set; } = new string[0];
public string[] Title { get; set; } = new string[0];
public string[] Of { get; set; } = new string[0];
public string[] NormalForTitle { get; set; } = new string[0];
}
由于 MS Json 反序列化器以前不支持像 Newtonsoft 那样转换为 $type,因此我也尝试像这样使用反射填充值(我已经删除了所有代码可读性的空值检查):
public static void Load()
{
Names = new Names();
foreach (var category in Names.GetType().GetProperties())
{
if (category is not null && !(category.GetGetMethod()?.IsStatic ?? false))
{
var categoryType = category.PropertyType;
foreach (var item in category.PropertyType.GetProperties())
{
var itemType = item.PropertyType;
var subTypeData = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(File.ReadAllText($"./Assets/Names/{categoryType.Name}/{itemType.Name}.json"));
var concreteObj = Activator.CreateInstance(itemType);
foreach (var key in subTypeData.Keys)
{
if (itemType.GetProperty(key) is not null && concreteObj is not null)
{
var prop = concreteObj.GetType().GetProperty(key);
var convertedValue = ConvertJsonType(subTypeData[key], subTypeData[key].ValueKind, out var isReferenceType);
// It fails here
prop.SetValue(
isReferenceType ? convertedValue : null,
!isReferenceType ? convertedValue : null
);
}
}
item.SetValue(concreteObj, null);
}
}
}
}
因此,它在层次结构中最深对象的prop.SetValue(...) 处失败,并根据要设置的值的类型出现不同的错误。
如果是引用,则会抛出 System.Reflection.TargetException : 'Object does not match target type' Exception
如果它是值,它会抛出一个System.Reflection.TargetException : 'Non-static method requires a target.'
知道我在反序列化方面没有问题,如此处所示,只有我使用动态类型的事实(我的直觉告诉我这实际上是问题......)
我没有添加 ConvertJsonType(...) 正文,因为它很实用且非常简单
我对“为什么”比“如何”更感兴趣,所以如果你能解释一下问题背后的“理论”,那会很有帮助:)
谢谢!
PS:我知道我可以以更易读/更高效的方式简化事情,但我必须通过反思来实现它以供个人学习:) System.Text.Json 命名空间也是如此,我不打算为此切换回 Newtonsoft
【问题讨论】:
标签: c# dynamic reflection .net-5 system.text.json