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



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

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…难以置信,但它适用于所有的场类型,牛顿软件。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));
        }
    }
}

我发现,牛顿软。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),以避免不必要的转换为string:

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

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

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

样本小提琴。

我不会把每个设置都标记为静态。相反,创建设置类的一个静态实例。例子:

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序列化/反序列化settings类。Net out of the box:

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

相关内容

  • 没有找到相关文章

最新更新