Enum属性第一次访问后改变顺序
本文关键字:改变 顺序 访问 属性 第一次 Enum | 更新日期: 2023-09-27 18:11:03
我们有以下enum:
public enum TrafficLight
{
[Description("../../images/dot-red.png")]
[AwesomeIcon("<i class='fa fa-lg fa-circle v4-red'></i>")]
Red = 0,
[Description("../../images/dot-yellow.png")]
[AwesomeIcon("<i class='fa fa-lg fa-circle v4-yellow'></i>")]
Yellow = 1,
[Description("../../images/dot-green.png")]
[AwesomeIcon("<i class='fa fa-lg fa-circle v4-green'></i>")]
Green = 2,
[Description("../../images/dot-gold.png")]
[AwesomeIcon("<i class='fa fa-lg fa-circle v4-gold'></i>")]
Gold = 3,
[Description("../../images/dot-grey.png")]
[AwesomeIcon("<i class='fa fa-lg fa-circle v4-grey'></i>")]
Grey = 99
}
AwesomeIcon
继承自DescriptionAttribute
类:
public class AwesomeIcon : DescriptionAttribute
{
public AwesomeIcon(string icon)
: base(icon)
{
}
}
问题是当枚举描述被访问不止一次时,属性的顺序发生了变化。例如,我们得到这样的描述:
public static string GetEnumDescription(Enum value, int index = 0)
{
var fi = value.GetType().GetField(value.ToString());
var attributes =
fi.GetCustomAttributes(typeof (DescriptionAttribute), false) as DescriptionAttribute[];
if(attributes == null)
{
return string.Empty;
}
if (attributes.Any() && index <= attributes.Length)
{
return attributes[index].Description;
}
return value.ToString();
}
第一次访问
GetEnumDescription(TrafficLight.Red);
//Returns "../../images/dot-red.png" as expected.
//Debug GetEnumDescription attributes variable
[0]Description
[1]AwesomeIcon
第二次访问
GetEnumDescription(TrafficLight.Yellow);
//Returns "<i class='fa fa-lg fa-circle v4-yellow'></i>"
// which is the value of AwesomeIcon.
//Debug GetEnumDescription attributes variable
[0]AwesomeIcon
[1]Description
顺序之后的每个访问都是AwesomeIcon
,然后是Description
。
问题是AwesomeIcon继承自Description并且它正在被拾取。如果数组中的顺序保持不变,就不会有问题,我可以通过索引引用它。
我以前没有经历过这种情况,有什么想法吗?
您可以确保您有一个DescriptionAttribute
(即使它是继承的),如:
var fi = value.GetType().GetField(value.ToString());
var attributes = fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
var myDescriptionAttribute =
attributes.FirstOrDefault(x => x.GetType() == typeof(DescriptionAttribute)) as DescriptionAttribute;
忘掉索引。属性不能保证顺序,所以索引是相当无用的。
通过使用x => x.GetType() == typeof(DescriptionAttribute)
,您可以获得精确的类型匹配。
我做了一个演示两种可能的方法(使用泛型或只是找到DescriptionAttribute
): https://dotnetfiddle.net/StUvqf
但基本上:
public static string GetEnumDescription(Enum value)
{
var fi = value.GetType().GetField(value.ToString());
var attributes = fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
var theDescriptionAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof (DescriptionAttribute)) as DescriptionAttribute;
if (theDescriptionAttribute == null)
{
return string.Empty;
}
return theDescriptionAttribute.Description;
}
或:
public static string GetEnumDescription<T>(Enum value)
where T : DescriptionAttribute
{
var fi = value.GetType().GetField(value.ToString());
var attributes = fi.GetCustomAttributes(typeof (T), false);
var theDescriptionAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof (T)) as T;
if (theDescriptionAttribute == null)
{
return string.Empty;
}
return theDescriptionAttribute.Description;
}
当然可能需要更多的null
检查,但我将把它留给你
作为一个额外的提示,FieldInfo.GetCustomAttributes
永远不会返回null(它可能返回一个空数组,但不是null),所以您可以删除null检查:-)
作为一种快速修复方法,您可以按名称对属性进行排序,这将帮助您每次都以相同的顺序获得它们。
var attributes =
fi.GetCustomAttributes(typeof (DescriptionAttribute), false) as object[];
if(attributes.Any())
{
// Ascending order
Array.Sort(attributes, (x, y) =>
String.Compare(x.GetType().Name, y.GetType().Name));
}
修复GetEnumDescription(Enum value, int index = 0)
:
if (attributes.Any() && index <= attributes.Length)
应该if (attributes.Any() && index < attributes.Length)