【问题标题】:Nested Dictionary with different types不同类型的嵌套字典
【发布时间】:2017-05-10 08:23:56
【问题描述】:

我的任务是在 c# 中构建数据集合。

每个数据集都有这些属性:

  • 类型
  • 名称(简短描述)
  • 服务字符串
  • HTTP方法

“类型”和“名称”属性具有一组已知且固定的值。

示例数据:

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

...等等。

为了最大程度地减少编码错误,并且由于条目列表是已知且已修复的,我为“类型”和“名称”创建了几个枚举。

示例数据:

enumTypes
enumUserFunctions
enumRightFunctions

...等等。

我也知道在代码中应该如何访问数据:

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

我正在尝试使用嵌套字典来实现此目标,但我面临的问题是嵌套字典具有不同的类型,具体取决于我尝试存储的数据集类型。

Dictionary<enumTypes, Dictionary<variableEnum, AutoPropertyWithValues>>

我如何轻松地实现我的目标?


编辑

根本原因是我的代码中有一些需要多次使用的对象,我想实现一种直观的方式来导航到它们。这就是我在 Sinatr 的建议下从我的根本想法中做出的。

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 ... */
}

最后一个问题。 有没有办法直接在定义中设置对象? 例如在 Do_User_Login 的定义中设置 ServiceUriString 和 HTTPMethod:

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

【问题讨论】:

  • 您可以嵌套字典,但使用 UserRights 类可能会更简洁。
  • 我完全不喜欢使用Dictionary 来保存配置。 AutoPropertyWithValue 是什么?答案实际上取决于您对值做了什么(如何填充和使用字典)。
  • 根本问题是什么?闻起来像是从配置文件 (JSON) 中获取值?
  • 根本原因是我的代码中有一些需要多次使用的对象,我想实现一种直观的方式来导航到它们。所有值都是固定的,需要硬编码。所以不,它与从配置文件中获取值无关;)

标签: c# dictionary types nested


【解决方案1】:

条目列表是已知且固定的

请勿使用此类动态结构(DictionaryList 等)。相当标准的属性,那么您不需要额外的枚举来识别类型:

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";
}

用法

var serviceString = configurationInstance.UserA.ServiceString;

如果你需要枚举它们,那么你可以使用反射或添加类似的方法

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

【讨论】:

  • 感谢您的建议,我是菜鸟,从来没有用过或看过这样的课程。您的示例中有没有办法在用户定义中设置“ServiceString”值?因为 UserA 形式的“ServiceString”与 UserB 不同;)我已经编辑了我最初的问题以添加到目前为止的进度。
  • "在用户定义中设置"ServiceString"值" - 你可以使用带参数的构造函数或object initializer,例如new User() { ServiceString = "something" }.
  • 谢谢,这正是我所需要的,甚至比我最初制定的更简单;)
【解决方案2】:

您可以通过以下方式简化它

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();

}

【讨论】:

  • 我认为 Sinatr 的解决方案更适合我的需要,但感谢您的建议,这是一种有趣的方法。
猜你喜欢
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 2015-06-28
  • 2018-01-29
  • 2021-12-20
  • 2016-01-11
  • 2018-05-31
相关资源
最近更新 更多