c# - 在 C# 中的静态类中使用 JsonConvert.DeserializeObject<T> 进行动态转换

标签 c# json dynamic casting json.net

我有一个公共(public)静态类Settings,我在其中存储一些公共(public)静态字段:

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()));

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

最佳答案

您想要使用重载 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 .

关于c# - 在 C# 中的静态类中使用 JsonConvert.DeserializeObject<T> 进行动态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40376315/

相关文章:

c# - SqliteDataReader 在 C# 中不起作用?

c# - 使用 XAML 属性在 RichTextBox 中插入图像

c# - 通过 Azure 函数的 SQL 连接仅适用于本地主机

c# - 我们可以强制 C# 编译器先运行构造函数吗?

python - 如何将 json 转换为 python 类?

json - 在 Dart 中将 Map 的所有键和值转换为 String

ios - swift : How to avoid duplicate entries in CoreData for implementation with JSON array?

dynamic - React Native 是否可以动态创建组件?

java - 我可以使字节数组的大小动态化吗?

arrays - 在c中对动态数组进行排序