kami
kami

Reputation: 274

Nested Dictionary with different types

I have the task to build a collection of data inside of c#.

Each data set has these attributes:

The attributes "Type" and "Name" have a known and fixed set of values.

Example Data:

Type: User
    -> Name: Get_Users_List
    -> Name: Add_User
    -> Name: Enable_User
    -> Name: Disable_User
Type: Rights
    -> Name: Get_Rights_List
    -> Name: Approve_User_Right

... and so on.

To minimize coding errors and because the list of entries is known and fixed I have created several enum's for the "Type"s and "Name"s.

Example Data:

enumTypes
enumUserFunctions
enumRightFunctions

...and so on.

I also know how the data should be accessed inside the code:

SomeCollection[enumType.User][enumUserFunctions.Add_User].ServiceString
SomeCollection[enumType.User][enumRightFunctions.Approve_User_Right].HTTPMethod

I'm trying to use nested dictionaries to achieve this goal, but I facing the problem that the nested dictionary is has a different type depending on the Dataset-Type I'm trying to store.

Dictionary<enumTypes, Dictionary<variableEnum, AutoPropertyWithValues>>

How do I comfortably achieve the goal I have?


Edit

The root cause is that I have some objects I need to use several times in my code, and I want to implement a intuitive way to navigate to them. This is what I is what I have made from my root idea after Sinatr's suggestion.

public class FunctionCollection
{
    public UserFunctions UserFunctions { get; } = new UserFunctions();
    public BaseDataFunctions BaseDataFunctions { get; } = new BaseDataFunctions();
    /* ... and so on ... */
}
public class UserFunctions
{
    public RestFunction Do_User_Login { get; set; } = new RestFunction();
    public RestFunction Do_User_Logout { get; set; } = new RestFunction();
    /* ... */
}
public class BaseDataFunctions
{
    public RestFunction Get_Product_List { get; set; } = new RestFunction();
    /* ... */
}
public class RestFunction
{
    public string ServiceUriString { get; set; }
    public HttpVerbs Method { get; set; }
    /* ... and so on ... */
}

Just one last question. Is there a way to set the objects directly in the definition? For Example setting ServiceUriString and HTTPMethod in the definition of Do_User_Login:

public RestFunction Do_User_Login { get; set; } = new RestFunction();

Upvotes: 0

Views: 459

Answers (2)

Sir Rufo
Sir Rufo

Reputation: 19116

You can simplify that by

public class MyConfig
{
    private readonly Dictionary<string, Dictionary<string, RestFunction>> _config = new Dictionary<string, Dictionary<string, RestFunction>>
    {
        [nameof( User )] = new Dictionary<string, RestFunction>
        {
            [nameof( UserSection.Add_User )] = new RestFunction { HttpMethod = "GET", ServiceString = "foo" },
            [nameof( UserSection.Get_Users_List )] = new RestFunction { HttpMethod = "GET", ServiceString = "foo" },
        },
        [nameof( Rights )] = new Dictionary<string, RestFunction>
        {
            [nameof( RightsSection.Approve_User_Rights )] = new RestFunction { HttpMethod = "GET", ServiceString = "foo" },
            [nameof( RightsSection.Get_Rights_List )] = new RestFunction { HttpMethod = "GET", ServiceString = "foo" },
        },
    };

    protected IDictionary<string, RestFunction> GetSectionValues( [CallerMemberName] string propertyName = null )
    {
        return _config[propertyName];
    }

    public UserSection User => new UserSection( GetSectionValues() );
    public RightsSection Rights => new RightsSection( GetSectionValues() );
}

public class RestFunction
{
    public string HttpMethod { get; set; }
    public string ServiceString { get; set; }
}

public abstract class ConfigSectionBase
{
    protected readonly IDictionary<string, RestFunction> _values;
    protected ConfigSectionBase( IDictionary<string, RestFunction> values )
    {
        _values = values;
    }

    protected RestFunction GetProperty( [CallerMemberName] string propertyName = null )
    {
        return _values[propertyName];
    }
}

public class UserSection : ConfigSectionBase
{
    public UserSection( IDictionary<string, RestFunction> values ) : base( values )
    {
    }

    public RestFunction Add_User => GetProperty();
    public RestFunction Get_Users_List => GetProperty();
}

public class RightsSection : ConfigSectionBase
{
    public RightsSection( IDictionary<string, RestFunction> values ) : base( values )
    {
    }

    public RestFunction Approve_User_Rights => GetProperty();
    public RestFunction Get_Rights_List => GetProperty();

}

Upvotes: 0

Sinatr
Sinatr

Reputation: 22042

the list of entries is known and fixed

Do not use such dynamic structures (Dictionary, List, etc.). Rather standard properties, then you don't need additional enumerations to identify types:

public class Configuration
{
    public User UserA { get; set; } = new User();
    public User UserB { get; set; } = new User();
    ...
}

public class User
{
    public string ServiceString { get; set; } = "whatever";
}

Usage

var serviceString = configurationInstance.UserA.ServiceString;

If you need to enumerate them, then you can either use reflection or add method similar to

public IEnumerable<User> GetUsers()
{
    yield return UserA;
    yield return UserB;
}

Upvotes: 1

Related Questions