2016-11-02 51 views
2

我有一个公共静态类设置,我在那里存放一些公共静态字段:与JsonConvert.DeserializeObject <T>动态铸造在静态类在C#

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(对象)。我试过:

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

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

回答

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

而且,由于第一Object参数FieldInfo.SetValue(Object, Object)是静态方法忽略了,你可能只想传递null清晰:

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

样品fiddle

+0

谢谢你的男人!有用!我将你的答案标记为“正确”,但是会使用heinzbeinz中的方法与“out of box”Json序列化。 – Breket

1

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

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); 
+0

谢谢。我会用你的方法... – Breket