【问题标题】:Deserializing a json file into a static class in C#在 C# 中将 json 文件反序列化为静态类
【发布时间】:2018-05-15 00:36:33
【问题描述】:

我有一个带有静态字段和 json 的静态类。

我可以将 json 反序列化为动态对象,因此我拥有所有字段,并且它们与类中的静态字段完全匹配。

如何使用反射枚举字段并将值从动态类复制到静态类字段?

我无法更改架构,使其成为单例等;它是共享代码,并且类将保持静态,因为它是共享库使用的全局共享设置对象。

解决方案需要使用反射,因为随着时间的推移,类会随着新成员的出现而演变。否则我可以编写一个自定义的反序列化器。


添加更多细节,但确实不多:

我有这个静态类:

static class A
{
    static int I;
    static string S;
}

以及与字段完全匹配的 json:

{
    "I" : 3,
    "S" : "hello"
}

var Data = JsonConvert.Deserialize<dynamic>(...);

我想用我从 json 反序列化的值将 A 类的静态字段初始化为一个动态对象。


另一个编辑:

我想出了类似于大卫写的东西,但是效率较低,因为我使用反序列化器来转换类型,所以大卫的解决方案更好。

这是我想出的:

foreach (var Destination in typeof(Settings).GetProperties())
{
    var Name = Destination.Name;
    var T = Destination.PropertyType;
    var Value = JsonConvert.DeserializeObject("\"" + JT[Name] + "\"", T);
    Destination.SetValue(null, Value);
}

【问题讨论】:

  • minimal reproducible example中显示代码,以便我们更好地理解问题。
  • 你不需要直接使用反射,只需使用动态JSON解析例如JToken.Parse。然后手动分配字段
  • 我添加了更多细节
  • @Camilo,我可以用jtoken.parse方法解析json,但是如何将每个值转换为静态类中匹配字段的类型?

标签: c# reflection


【解决方案1】:

你可以很容易地做到这一点,方法是拥有一个匹配的非静态类,获取源和目标的属性并循环遍历每一个。例如,假设我们有两个类:

public static class A
{
    public static int I { get; set; }
    public static string S { get; set; }
}

public class B
{
    public int I { get; set; }
    public string S { get; set; }
}

我们现在可以这样做了:

public void MapToStaticClass(B source)
{
    var sourceProperties = source.GetType().GetProperties();

    //Key thing here is to specify we want the static properties only
    var destinationProperties = typeof(A)
        .GetProperties(BindingFlags.Public | BindingFlags.Static);

    foreach (var prop in sourceProperties)
    {
        //Find matching property by name
        var destinationProp = destinationProperties
            .Single(p => p.Name == prop.Name);

        //Set the static property value
        destinationProp.SetValue(null, prop.GetValue(source));
    }
}

另一种选择是反序列化为JToken 并将其与反射结合使用:

var source = JsonConvert.DeserializeObject<JToken>(json);

然后:

public void MapJTokenToStaticClass(JToken source)
{
    var destinationProperties = typeof(A)
        .GetProperties(BindingFlags.Public | BindingFlags.Static);

    foreach (JProperty prop in source)
    {
        var destinationProp = destinationProperties
            .SingleOrDefault(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase));
        var value = ((JValue)prop.Value).Value;

        //The ChangeType is required because JSON.Net will deserialise
        //numbers as long by default
        destinationProp.SetValue(null, Convert.ChangeType(value, destinationProp.PropertyType));
    }
}

【讨论】:

  • 这正是我想要避免的,因为这个类中的字段被添加为共享库需要的项目;否则我会编写一个自定义反序列化器,问题就会得到解决。但我需要想出一个基于反射的方法来适应我无法控制的变化。
  • 我提到它需要使用反射,但也许我应该解释一下原因。我将编辑问题
  • 是的,这个答案使用反射!
  • 你说得对,问题不够清晰;希望这个问题现在得到解决。
  • 好吧,我为你添加了另一个选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
相关资源
最近更新 更多