1. Hello everyone!
    I've run into a strange problem - I can't proparly save and ready dictionaries and my own custom classes form the Config.
    Here is what I'm trying to do:
    I have something like this:

    Code:
        private Dictionary<string, string> dict1;
        private Dictionary<string, string> dict2;
    And what I wanted is to save it to the config and read it back.
    This is the code I'm using to get data in\out of config:
    Code:
    private void GetConfig<T>(string Key, ref T var)        {
            if (Config[Key] != null)
            {
                var = (T)Convert.ChangeType(Config[Key], typeof(T));
            }
            Config[Key] = var;
        }
    Fill dicts with something and trying to get it to config, and I expect it to work:
    Code:
    private void LoadConfigValues()
    {
        dict1 = new Dictionary<string, string>()
        {
            ["Test1"] = "test1",
            ["Test2"] = "test2"    
        }
        dict2 = new Dictionary<string, string>()
        {
            ["Test3"] = "test3",
            ["Test4"] = "test4"
        }
        GetConfig("Dictionary 1", ref dict1);
        Getconfig("Dictionary 2", ref dict2);
        SaveConfig();
    }
    
    But here comes an error-
    Code:
    Failed to initialize plugin 'test v1.0.0' (InvalidCastException: Value is not a convertible object: System.Collections.Generic.Dictionary`2[System.String,System.Object] to System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]])
    So the problem is - Config[Key] returns me not Dictionary<string,string>, but Dictionary<string,object>
    How can I avoid it?

    The only solution I've found so far is doing something creepy like that:
    Code:
    private Dictionary<string, string> Dict1;
    private Dictionary<string, string> Dict2;private void LoadConfigValues()
    {
        Dictionary<string, object> dict1 = new Dictionary<string, object>()
        {
            ["Test1"] = "test1",
            ["Test2"] = "test2"    
        }
        Dictionary<string, object> dict2 = new Dictionary<string, object>()
        {
            ["Test3"] = "test3",
            ["Test4"] = "test4"
        }
        GetConfig("Dictionary 1", ref dict1);
        Getconfig("Dictionary 2", ref dict2);
        foreach(var item in dict1)
        {
            Dict1.Add(item.Key, item.Value.ToString());
        }
        foreach(var item in dict2)
        {
            Dict2.Add(item.Key, item.Value.ToString());
        }
        SaveConfig();}
    
    And that's creepy.



    About classes - that's the over question.
    Let's say I have a class:
    Code:
           class DnN
        {
            public Dictionary<string, object> Day { get; set; }
            public Dictionary<string, object> Night { get; set; }
            public DnN()
            {
                Day = new Dictionary<string, object>(); //Same problem as above, so this time I decided to just 
                Night = new Dictionary<string, object>(); // Change Dictionaty<string,float> to <string,object>
            }
        }
    Is there any way to store it?
    [DOUBLEPOST=1492192679][/DOUBLEPOST]Also - if anyone would be able to tell me why this code works:
    Code:
    private void GetConfig<T>(string Key, ref T var)
        {
            if (Config[Key] != null)
            {
                var = (T)Convert.ChangeType(Config[Key], typeof(T));
            }
            Config[Key] = var;
        }
    While this(just to be able to save config into the sub directories) gives me cast error:

    Code:
            private void GetConfig<T>(ref T value, params object[] args)
        {
            List<string> stringArgs = (from arg in args select arg.ToString()).ToList<string>();
            if (Config.Get(stringArgs.ToArray()) != null)
            {
                value = (T)Convert.ChangeType(Config.Get(stringArgs.ToArray()), typeof(T));
            }
            Config.Set(args, value);
        }
     
  2. Ooook.... for thoses who would got here - here is an example how to do so - classes.
    So, here is an example of saving classes to the DynamicConfigFile:
    Code:
    using Newtonsoft.Json;
    //Code
    private PluginConfig config; //notice that my var starts from lower case. Config - in-build var of type DynamicConfigFile with the name of the plugin.
    //Code
    #region Config
    private class PluginConfig
    {
    [JsonProperty("This is the text, that would be assossiated with the config line")]
    public string Permission;
    [JsonProperty("Is it working?")]
    public bool IsIt;
    [JsonProperty("Here is some description of this variable")]
    public DealWithIt DoYou;
    public static PluginConfig DefaultConfig()
    {
    Permission = "coolplugin.use",
    IsIt = true,
    DoYou = new DealWithIt(){
    {
        Yeah = true,
        Nope = false
    }
    };
    }
    private class DealWithIt
    {  
    [JsonProperty("Description of sub var 1")]
    public bool Yeah;
    [JsonProperty("Description of sub var 2")]
    public bool Nope;
    }
    #endregion#region Config init
    protected override void LoadDefaultConfig()
    {
    PrintWarning("Generating default config file");
    config = PluginConfig.DefaultConfig();
    //we don't have to save config to the file yet - due to override SaveConfig function
    }
    protected override void LoadConfig()
    {
    base.LoadConfig();
    //we have loaded config file, now - reading it as the object and doing what we want wile loading config file.
    config = Config.ReadObject<PluginConfig>();
    permission.RegisterPermission(config.Permission, this);
    }
    protected override void SaveConfig()
    {
    //Using WriteObject to store out object to the file.
    Config.WriteObject(config);
    }
    #endregion
     
  3. If you want to save just a dictionary, or list, or any over build-in classes and objects - you can use this construction:
    Code:
    private Dictionary<string,List<string>> mydict;
    #region Config Initialization
    protected override void LoadDefaultConfig()
    {
    PrintWarning("New config file created");
    mydict = new Dictionary<string,List<string>>()
    {
    ["string 1"] = new List<string>()
    {
        "substring 1_1","substring 1_2","substring 1_3"
    },
    ["string 2"] = new List<string>()
    {
        "substring 2_1","substring 2_2","substring 2_3"
    },
    }
    }
    protected override void LoadConfig()
    {
    base.LoadConfig();
    mydict = Config.ReadObject<Dictionary<string,List<string>>>();
    foreach(var str in mydict.Keys)
    permission.RegisterPermission(str, this);
    }
    protected override void SaveConfig()
    {
    Config.WriteObject(config);
    }
    #endregion
    For saving data you can use this:
    Code:
    private Dictionary<string, bool> MyDict = new Dictionary<string, bool>();
    private void SaveData()
    {
    Interface.Oxide.DataFileSystem.WriteObject(Title, MyDict);
    }
    void LoadData()
    {
    try
    {
    MyDict = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, bool>>(Title);
    }
    catch (Exception ex)
    {
    PrintError($"Failed to load data file (is the file corrupt?) ({ex.Message})");
    MyDict = new Dictionary<string, bool>();
    }
    }
     
  4. Hey, @Wulf , why my post is awaiting for the approval? there is no even a links in there....
    Also - maybe you can add this to the docs? As well as the chat\console commands? Cos there is only covalence [Command] Listed there....
    And JsonProperty - this is something not much people know =)
    P.S. Ok, my mistake. link removed. Didn't notice it. This was just a copy-paste from one of my plugin)
    P.P.S - I didn't see the thread tools for some reason, and can't put prefix on it, so...