是否可以根据C#中键/值对上的键获得值类型?

时间:2017-08-18 14:30:21

标签: c# dictionary enums

让我举一个简单的例子来更好地理解问题

图书馆持有:

enum Keys
{
    [Description("Color select")]
    ColorSelection,

    [Description("Day select")]
    DaySelection,

    [Description("Gender select")]
    GenderSelection
}


enum Color
{
    [Description("White color")]
    White,

    [Description("Black color")]
    Black,

    [Description("Brown color")]
    Brown
}
enum Day
{
    [Description("Monday")]
    Monday,

    [Description("Tueday")]
    Tuesday,

    [Description("Wednesday")]
    Wednesday
}

enum Gender
{
    [Description("Male gender")]
    Male,

    [Description("Female gender")]
    Female            
}

来自客户我希望如此:

Dictionary<Keys, ??> values = new Dictionary<Keys, ??>();

values.Add(Keys.ColorSelection, <Auto suggest color>);
values.Add(Keys.DaySelection, <Auto suggest day>); 

我可以修改库以将values列为Enum但是,我希望客户端根据密钥自动建议使用过滤器的值。

注意:
    1.我不希望Class(Model)具有属性作为相应的类型,因为库中有很多可用的键,客户端会选择少量并提供值。
    2.我不能单独将值作为List<Values>,因为某些情况下将使用不同的键具有相同的description值。例如:&#34;是/否值将与不同的键相同&#34;

有什么建议吗?提前谢谢..

3 个答案:

答案 0 :(得分:0)

您可以将字典声明为:

var dictionary = new Dictionary<Keys, int>();

然后使用一个方法将它封装在您自己的自定义类中,该方法使用键的Keys值来使用相应的枚举来解释该值。

这里的整个问题看起来像代码味道。

答案 1 :(得分:0)

我同意@ owen-pauling;我认为你应该修改你目前的设计。但根据您提供的示例,您可以使用Dictionary<Keys, int>处理此问题的一种方法:

Dictionary<Keys, int> values = new Dictionary<Keys, int>();
values.Add(Keys.ColorSelection, Convert.ToInt32(Color.Black));
values.Add(Keys.GenderSelection, Convert.ToInt32(Gender.Male));
values.Add(Keys.DaySelection, Convert.ToInt32(Day.Wednesday));

foreach (KeyValuePair<Keys, int> kv in values)
{
    dynamic enumValue = null;

    switch (kv.Key)
    {
        case Keys.ColorSelection:
            enumValue = Enum.Parse(typeof(Color), Convert.ToString(kv.Value));
            break;

        case Keys.DaySelection:
            enumValue = Enum.Parse(typeof(Day), Convert.ToString(kv.Value));
            break;

        case Keys.GenderSelection:
            enumValue = Enum.Parse(typeof(Gender), Convert.ToString(kv.Value));
            break;
    }

    Console.WriteLine(String.Format("Enum value: {0}", enumValue));
}

/* Output:
Enum value: Black
Enum value: Male
Enum value: Wednesday
*/

如果您愿意进行更改,也许从客户端保留选择的类就足够了。以下是List<DetailSelection>的示例:

public class DetailSelection
{
    public DetailSelection() { }

    public Type SelectionType { get; set; }
    public string Description { get; set; }
    public int EnumValue { get; set; }
}

List<DetailSelection> details = new List<DetailSelection>();
details.Add(new DetailSelection() {
    Description = "Color description",
    SelectionType = typeof(Color),
    EnumValue = Convert.ToInt32(Color.Black)
});
details.Add(new DetailSelection() {
    Description = "Day description",
    SelectionType = typeof(Day),
    EnumValue = Convert.ToInt32(Day.Wednesday)
});
details.Add(new DetailSelection() {
    Description = "Gender description",
    SelectionType = typeof(Gender),
    EnumValue = Convert.ToInt32(Gender.Male)
});

foreach (var detail in details)
{
    var enumValue = Enum.Parse(detail.SelectionType, Convert.ToString(detail.EnumValue));

    Console.WriteLine(String.Format("Enum value: {0}", enumValue));
}

/* Output:
Enum value: Black
Enum value: Wednesday
Enum value: Male
*/

在任何一种情况下,我都可能会尝试退后一步并重新评估您的设计;只是一个友好的建议。 : - )

我认为你不应该使用Dictionary<TKey, TValue>;由于必须是唯一的,因此您将限制客户端只有一个ColorSelection,GenderSelection,DaySelection等。

答案 2 :(得分:0)

我认为最简单(也可能是最好的)解决方案是Milney在评论中提出的建议:

class Properties
{
    Color? ColorSelection { get; set; }
    Day? DaySelection { get; set; }
    Gender? GenderSelection { get; set; }
}

客户代码:

Properties values = new Properties();

values.ColorSelection = < Auto suggest color >;
values.DaySelection = < Auto suggest day >;

但是,您似乎担心有数百个属性,其中只有少数属性具有值。这可能是过早优化的问题:它感觉很浪费,但开发人员的时间比这种方法可能花费的任何内存资源都要高出几个数量级。但是,如果这真的困扰您,或者您通过负载测试确定这实际上是一个问题,您可以优化您的实现,而无需更改客户端代码:

class Properties
{
    private Dictionary<Type, int> values = new Dictionary<Type, int>();
    Color? ColorSelection
    {
        get
        {
            return values.TryGetValue(typeof(Color), out int i)
                ? (Color?)i
                : null;
        }
        set
        {
            values[typeof(Color)] = (int)value;
        }
    }
    ...
}

这会使您的API完全相同,但会像您要求的那样将所有值存储在字典中。如果您愿意,也可以将Type替换为Keys枚举。实际上,您可以在Properties类上创建通用的“添加”方法,以防您希望允许客户端代码以编程方式根据运行时已知的数据添加值。但是当客户想要智能感知建议时,他们可以使用这些属性。

如果你选择这条路线,我建议使用T4模板来生成你的属性类,这样你就不会编写大量的样板代码。