多个枚举说明

时间:2015-10-02 06:40:42

标签: c# enums

我定义了以下enum

public enum DeviceType
{
    [Description("Set Top Box")]
    Stb = 1,
    Panel = 2,
    Monitor = 3,
    [Description("Wireless Keyboard")]
    WirelessKeyboard = 4
}

我正在使用Description属性来允许我提取更多用户可读的枚举版本以在UI中显示。我使用以下代码获得描述:

var fieldInfo = DeviceType.Stb.GetType().GetField(DeviceType.Stb.ToString());

var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

var description = (attributes.Length > 0 ? attributes[0].Description : DeviceType.Stb.ToString());

上面的代码会给我:description = "Set Top Box"。如果没有设置Description属性,它将为我提供枚举的字符串值。

我现在想为每个枚举添加第二个/自定义属性(例如,名为“值”)。例如:

public enum DeviceType
{
    [Description("Set Top Box")]
    [Value("19.95")]
    Stb = 1,
    [Value("99")]
    Panel = 2,
    [Value("199.99")]
    Monitor = 3,
    [Description("Wireless Keyboard")]
    [Value("20")]
    WirelessKeyboard = 4
}

我需要提取新的Value属性,就像我目前使用Description属性一样。

是否可以将现有的Description属性扩展为以某种方式包含新的Value属性,还是最好分别创建新属性?

4 个答案:

答案 0 :(得分:17)

创建一个名为DeviceInformation ...

的新属性
[AttributeUsage(AttributeTargets.All)]
public class DeviceInformationAttribute : DescriptionAttribute
{
    public DeviceInformationAttribute(string description, string value)
    {
        this.Description = description;
        this.Value = value;
    }

    public string Description { get; set; }
    public string Value { get; set; }
}

您还可以使用扩展方法检索任何属性的值

static void Main(string[] args)
{
    var info = DeviceType.Stb.GetAttribute<DeviceInformationAttribute>();
    Console.WriteLine("Description: {0}\nValue:{1}",info.Description, info.Value);

}

public static class Extensions
{
    public static TAttribute GetAttribute<TAttribute>(this Enum enumValue)
            where TAttribute : Attribute
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<TAttribute>();
    }
}

public enum DeviceType
{
    [DeviceInformation("foobar", "100")]
    Stb = 1,
}

修改

回应评论

  @Aydin Adn我很喜欢使用扩展方法,非常好!您是否有针对DeviceType.Panel案例的解决方案,该解决方案没有描述,但需要Value属性? (见Patrick的回答评论)

 [AttributeUsage(AttributeTargets.All)]
public class DeviceInformationAttribute : Attribute
{
    public DeviceInformationAttribute(string description)
    {
        this.Description = description;
    }

    public DeviceInformationAttribute(decimal value)
    {
        this.Description = string.Empty;
        this.Value = value;
    }

    public DeviceInformationAttribute(string description, decimal value)
    {
        this.Description = description;
        this.Value = value;
    }


    public string Description { get; set; }
    public decimal Value { get; set; }
}

答案 1 :(得分:13)

是的,这很容易做到。只需派生现有的DescriptionAttribute类:

[AttributeUsageAttribute(AttributeTargets.All)]
public class DescriptionWithValueAttribute : DescriptionAttribute
{
    public DescriptionWithValueAttribute(string description, string value) : base(description)
    {
        this.Value = value;
    }

    public string Value { get; private set; }
}

然后你可以像这样使用它:

public enum DeviceType
{
    [DescriptionWithValue("Set Top Box", "19.95")]
    Stb = 1,
}

检索属性的代码将保持几乎相同,只需替换类型名称。

答案 2 :(得分:1)

你想要做的是:创建一个属性来描述更具体的枚举:这是你如何做到的:

public class EnumValue : Attribute
{
    public Decimal Value { get; private set; }
    public EnumValue(Decimal value)
    {
        this.Value = value;
    }
}

这可以通过此扩展方法使用:

private static Decimal GetEnumCustomAttribute(this Enum leEnum, Typ typ)
    {
        try
        {
            if (leEnum == null) throw new ArgumentNullException("leEnum");

            Type type = leEnum.GetType();

            MemberInfo[] memInfo = type.GetMember(leEnum.ToString());

            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumValue), false);

                if (attrs != null && attrs.Length > 0)
                    return ((EnumValue)attrs[0]).Value;
            }

            return Decimal.MinValue;
        }
        catch (Exception)
        {
            throw;
        }
    }

试一试!

答案 3 :(得分:1)

为什么不在一个班级做这件事。一开始还有点工作,但是:

  • 使用其他值更容易扩展
  • 可以使用辅助函数来创建公共元素(请参阅Simple()
  • 在运行时更高效,因为没有反射来获取值
  • 在Wpf中绑定更轻松"{Binding namespace:DeviceType.All}""{Binding SomeDeviceTypeProperty.Value}"
  • 没有无效的值var invalid = (DeviceType)100;

示例代码

public class DeviceType
{
    public static readonly DeviceType
        Stb = new DeviceType("Stb", "Set Top Box", 19.95),
        Panel = new DeviceType("Panel", 99),
        Monitor = new DeviceType("Monitor", 19.95),
        Cable = Simple("Cable"),
        Connector = Simple("Connector"),
        WirelessKeyboard = new DeviceType("WirelessKeyboard", "Wireless Keyboard", 20);

    private static readonly IEnumerable<DeviceType> _all = typeof(DeviceType)
        .GetFields(BindingFlags.Public | BindingFlags.Static).Select(f => (DeviceType)f.GetValue(null)).ToArray();
    public static IEnumerable<DeviceType> All { get { return _all; } }

    public static DeviceType Parse(string name)
    {
        foreach (var item in All)
        {
            if (item.Name == name)
                return item;
        }
        throw new KeyNotFoundException(name);
    }

    private static DeviceType Simple(string name)
    {
        return new DeviceType(name, name, 9.95);
    }
    private DeviceType(string name, decimal value) : this(name, name, value) { }
    private DeviceType(string name, string description, decimal value)
    {
        Name = name;
        Description = description;
        Value = value;
    }

    public string Name { get; private set; }
    public string Description { get; private set; }
    public decimal Value { get; private set; }

    public override string ToString()
    {
        return Name;
    }
}
相关问题