【问题标题】:Dynamic casting with JsonConvert.DeserializeObject<T> in static class in c#在 C# 的静态类中使用 JsonConvert.DeserializeObject<T> 进行动态转换
【发布时间】:2016-11-02 17:52:00
【问题描述】:

我有一个公共静态类设置,我在其中存储了一些公共静态字段:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Reflection;

namespace testApp {
    public static class Settings {
        public static int appWidth = 800;
        public static int appHeight = 600;
        public static int layotCols = 1;
        public static int layotRows = 1;
        public static string TestString = "test";
        public static double TestFloat = 1.4;
        public static string[] TestStringArray = new[] { "1", "ee", "rrr"};
        public static List<string> TestStringArray1 = new List<string>() { "1", "2"};
        public static Dictionary<string,string> TestStringArray2 = new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
   }
}

现在我想将所有字段保存到文件中,但能够添加新字段而无需“手动”保存和读取它们。

我决定使用我的动态和反射技能,将所有字段列出到 ExpandoObject,然后是 JObject,然后是 File.WriteAllText 到“settings.ini”... 难以置信,但它适用于 Newtonsoft.Json 可以序列化的所有字段类型:

public static void saveSettings() {
    Type type = typeof(Settings); // Settings is static class with static properties

    dynamic dObject = new ExpandoObject();
    var exObject = dObject as IDictionary<String, object>;

    foreach(var setting in type.GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)) {
        exObject[setting.Name] = Convert.ChangeType(setting.GetValue(null), setting.FieldType); 
    }

    JObject obj = new JObject();
    obj = JObject.FromObject(dObject);

    File.WriteAllText("settings.ini", obj.ToString());
}

但是现在我在阅读这个文本文件时遇到了一些麻烦。 我使用了标准的反射方法,只能读取几种数据类型,但可以读取数组和其他数据类型:

public static void loadSettings() {
    var settingsFile = File.ReadAllText("settings.ini");
    JObject obj = JObject.Parse(settingsFile);

    Type type = typeof(Settings);
    foreach(var setting in type.GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)) {
        if(obj[setting.Name]?.ToString() != null) {
            setting.SetValue(setting, Convert.ChangeType(obj[setting.Name],setting.FieldType));
        }
    }
}

我发现,Newtonsoft.Json 还可以使用 JsonConvert.DeserializeObject(object) 反序列化对象并将其转换为多种类型。我试过了:

setting.SetValue(setting, JsonConvert.DeserializeObject<setting.FieldType>(obj[setting.Name].ToString()));

但是它给出了编译错误...你能帮帮我吗?

【问题讨论】:

    标签: c# json dynamic casting json.net


    【解决方案1】:

    你想使用重载JsonConvert.DeserializeObject(String, Type)

    setting.SetValue(setting, JsonConvert.DeserializeObject(obj[setting.Name].ToString(), setting.FieldType));
    

    或者,您可以使用JToken.ToObject(Type) 并避免不必要的字符串转换:

    setting.SetValue(setting, obj[setting.Name].ToObject(setting.FieldType));
    

    而且,由于静态方法忽略了 FieldInfo.SetValue(Object, Object) 的第一个 Object 参数,为了清楚起见,您可能只想传递 null:

    setting.SetValue(null, obj[setting.Name].ToObject(setting.FieldType));
    

    示例fiddle

    【讨论】:

    • 谢谢你!有用!我将您的答案标记为“正确”,但将使用带有“开箱即用”Json 序列化的 heinzbeinz 的方法。
    【解决方案2】:

    我不会将每个设置都标记为静态。而是创建设置类的一个静态实例。示例:

    public class Settings
    {
        public int appWidth = 800;
        public int appHeight = 600;
        public int layotCols = 1;
        public int layotRows = 1;
        public string TestString = "test";
        public double TestFloat = 1.4;
        public string[] TestStringArray = new[] { "1", "ee", "rrr"};
        public List<string> TestStringArray1 = new List<string>() { "1", "2"};
        public Dictionary<string,string> TestStringArray2 = new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
    }
    
    public static class App
    {
        public static Settings settings = new Settings();
    }
    

    您现在可以简单地使用开箱即用的 Json.Net 序列化/反序列化设置类:

    File.WriteAllText("settings.ini", JsonConvert.SerializeObject(App.settings));
    
    JsonConvert.PopulateObject(File.ReadAllText("settings.ini"), App.settings);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      相关资源
      最近更新 更多