2016-11-02 53 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