Search code examples
c#genericsdictionaryextensible

C# - Extensible method for adding variable types to a dictionary management class


I am currently working on a system for storing and retrieving data from a master dictionary class. Imagine something like this:

public class Manager {
    Dictionary<string, Category> _categories;

    public T GetValue<T>(string category, string id){
        return _categories[category].GetValue<T>(id);
    }
}

public class Category {
    Dictionary<string, Category> _subCategories;

    // How could I approach something like this?
    Dictionary<T, Dictionary<string, IElementExample<T>> _categoryDict;

    public T GetValue<T>(string id){
        if (_categoryDict.ContainsKey(T)){
            return _categoryDict[T][id];
        }
        return default(T);
    }
    public SetValue<T>(string id, T value){
        if (_categoryDict.ContainsKey(T)){
            if (_categoryDict[T].ContainsKey(id)){
                _categoryDict[T][id] = value;
            } else {
                _categoryDict[T].Add(id, value);
            }
        } else {
            _categoryDict.Add(T, new Dictionary<string, IElementExample<T>>());
            _categoryDict[T].Add(id, value);
        }
    }
}

//
public interface IElementExample<T> {
    T Value {get;set;}
    string Id {get;set;}
    string Comment{get;set;}

    string Serialize();
    void Deserialize(string serial);
}

public class StringElement : IElementExample<string> {
    string m_value;
    string m_id;
    string m_comment;

    string Value { get { return m_value; }}
    string Id { get { return m_id; }}
    string Comment { get { return m_comment; }}

    string Serialize(){

    }
    void Deserialize(){

    }
}

The thing that is tripping me up is that obviously I can't actually have Dictionary<T, Dictionary<string, IElementExample<T>>. Does anyone have any thoughts on how I might be able to accomplish something like that though?

The goal here is to create a master location where a lot of data can be stored (for game configuration variables), which I will then serialize/deserialize to/from XML. I have something that works for this already, and it works great, but it is impossible to add support for new data types without editing the Manager/Category classes to add support (at the moment instead of GetValue it is GetString/GetFloat/GetInt/GetBool/GetVector3... etc).

I can ensure that it only actually works with classes that are designed to work with it by adding "where" type constraint to ensure that it implements my interface. I'm just not sure how to go about setting up my "category" class in such a way that it can store and retrieve any "IExampleInterface<>" - if it is even possible.

I'd like to be able to use this for different projects that all contain the major types (string/int/float/bool...) - but also have their own custom structs and classes.

Thank you in advance for any input on this matter, I've been trying to figure it out on my own - but it's getting the better of me for sure.


Solution

  • I didn't work through all the code but it looks like you want a

     Dictionary<object, Dictionary<string, object> _categoryDict;
    

    or maybe a

    Dictionary<Type, Dictionary<string, object> _categoryDict;
    

    You correctly discovered that generics are not 'dynamic'. If you want to mix different types, you will need type-casting.