Hi!
I produce this in the config:
With the code:Code:"Test": { "Test List": { "1": [ "{playername} Test 1.", "{playername} Test 1.", "{playername} Test 1." ], "2": [ "{playername} Test 2.", "{playername} Test 2.", "{playername} Test 2." ] }, },
And when the plugin is reloaded and it tries to read that from the config it produces the following error:Code:public static List<string> Alist = new List<string> { "{playername} Test 1.", "{playername} Test 1.", "{playername} Test 1." }; public static List<string> Blist = new List<string> { "{playername} Test 2.", "{playername} Test 2.", "{playername} Test 2." }; public Dictionary<int, List<string>> TestList { get; private set; } = new Dictionary<int, List<string>> { {1, Alist}, {2, Blist}, }; private T GetConfig<T>(string category, string setting, T defaultValue) { var data = Config[category] as Dictionary<string, object>; object value; if (data == null) { data = new Dictionary<string, object>(); Config[category] = data; ConfigUpdated = true; } if (data.TryGetValue(setting, out value)) { return (T)Convert.ChangeType(value, typeof(T)); //**Error is thrown here**. } value = defaultValue; data[setting] = value; ConfigUpdated = true; return (T)Convert.ChangeType(value, typeof(T)); } private void LoadConfig() { TestList = GetConfig("Test", "Test List", TestList); } void OnServerInitialized() { LoadConfig(); }
I'm sure the fix is quite simple but my brain is failing me at the moment, so any help is greatly appreciated.Code:Failed to call hook 'OnServerInitialized' on plugin 'GUIAnnouncements v1.21.68' (InvalidCastException: Value is not a convertible object: System.Collections.Generic.Dictionary`2[System.String,System.Object] to System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Generic.List`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]])
Thanks!
Config InvalidCastException Dictionary<int, List<string>>
Discussion in 'Rust Development' started by JoeSheep, Mar 15, 2017.
-
What does typeof(T) print?
-
Code:System.Collections.Generic.Dictionary`2[System.Int32,System.Collections.Generic.List`1[System.String]]
Code:System.Collections.Generic.Dictionary`2[System.String,System.Object]
-
Convert.ChangeType is presumably just a shallow conversion, i.e. it converts the type of the value, but not the type of each of the values stored in that value.
-
-
Would I need to "manually" rebuild the object which in this case is a dictionary containing lists as values, into a new dictionary and set it to the variable I am using my code to read from?
-
Would Oxide's DynamicConfigFile.cs be able to handle that cast? I can't even remember why I stopped using it.
-
I had this same issue also for a while, but now I just create a wrapper class to contain the data dictionaries in my plugins and just do a ReadObject/WriteObject to load/save the config. The casting/type assignment seems to work fine that way.
-
I ended up with the following to get what I wanted though:
Code:public Dictionary<int, List<object>> newPlayerAnnouncementsList { get; private set; } = new Dictionary<int, List<object>> { {1, new List<object>{ "1st Join {playername} New player announcement 1.", "1st Join {playername} New player announcement 2.", "1st Join {playername} New player announcement 3." } }, {2, new List<object>{ "2nd Join {playername} New player announcement 1.", "2nd Join {playername} New player announcement 2.", "2nd Join {playername} New player announcement 3." } }, {3, new List<object>{ "3rd Join {playername} New player announcement 1.", "3rd Join {playername} New player announcement 2.", "3rd Join {playername} New player announcement 3." } }, }; private void LoadGUIAnnouncementsConfig() { newPlayerAnnouncementsList = GetConfig("New Player Announcements", "Announcements List (Show On This Many Joins : List To Show)", newPlayerAnnouncementsList); } private T GetConfig<T>(string category, string setting, T defaultValue) { var data = Config[category] as Dictionary<string, object>; object value; if (data == null) { data = new Dictionary<string, object>(); Config[category] = data; ConfigUpdated = true; } if (data.TryGetValue(setting, out value)) { //Added this if statement if (setting == "Announcements List (Show On This Many Joins : List To Show)") { var keyType = typeof(T).GetGenericArguments()[0]; var valueType = typeof(T).GetGenericArguments()[1]; var dict = (IDictionary)Activator.CreateInstance(typeof(T)); foreach (var key in ((IDictionary)value).Keys) { dict.Add(Convert.ChangeType(key, keyType), Convert.ChangeType(((IDictionary)value)[key], valueType)); } return (T)dict; } return (T)Convert.ChangeType(value, typeof(T)); } value = defaultValue; data[setting] = value; ConfigUpdated = true; return (T)Convert.ChangeType(value, typeof(T)); }//Used later for changing the list to strings private List<string> ConvertObjectListToString(object value) { if (value is List<object>) { List<object> list = (List<object>)value; List<string> strings = list.Select(s => (string)s).ToList(); return strings; } else return (List<string>)value; } void OnServerInitialized() { LoadGUIAnnouncementsConfig(); }
(I also can't seem to change this thread to solved for some reason)