我定义了以下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
属性,还是最好分别创建新属性?
答案 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()
)"{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;
}
}