具有标志属性的友好枚举字符串
Friendly Enum Strings With Flags Attribute
在细读了一些关于在 C# 中为枚举值一般创建对友好字符串的访问的常见方法的其他问题后 this answer 似乎是我最好的通用解决方案,其中友好字符串可以放在定义中使用 DescriptionAttribute
s.
的枚举
我将其实现为扩展方法,但很快意识到它仅适用于未指定 [Flags]
属性的标准枚举。对于存在该属性的情况,我不完全确定执行此操作的最佳方法。
由于 flags 属性意味着可以同时选择多个值,因此使用单个 "friendly string" 没有意义。我正在考虑以相同的方式定义友好的字符串,但是重载扩展方法以采用特定的枚举类型,它会 return a List<string>
为所有选定的值提供友好的字符串。
上述解决方案可行,但我觉得会有很多代码重复,因为每个使用 Flags 属性的枚举都需要它自己的扩展方法,因为枚举只能由 System.Enum
继承,消除了我创建基本类型的能力。如果我能有一个更通用的方法来处理这个问题,如果 flags 属性存在则检查枚举然后 return 以下之一:
会更好
- 单个字符串(如果没有 Flags),列表(如果有 Flags)- 签名 returns
object
- 单个字符串(如果没有 Flags),列表(如果有 Flags)- 签名 returns
dynamic
- 如果未指定标志,则可能仅包含一个值的列表 - 签名 returns
List<string>
我觉得这个问题可能是 "having my cake and eating it too" 的情况,因为我宁愿在获取友好字符串并删除代码重复数据后不必进行额外的检查。有没有什么技巧或好方法可以做到这一点而不是乱七八糟的黑客?
使用 enum.ToString()
获取 "unfriendly" 字符串(其中 enum 是您的 Enum 变量)。编写一个可重用的扩展方法,将 UnfriendlyString 转换为友好的 "unfriendly string"(例如,在有大写字母或类似字母的地方插入 space-小写字母)。
对于[Flags]
,您可以Split
不友好的字符串,转换每个子字符串,也许再次Join
;或者您的扩展方法可以考虑逗号。
您可以像 link 的答案一样编写方法,但支持标志枚举和 return 逗号分隔的字符串,例如:
public static string GetDescription(Enum value)
{
Type type = value.GetType();
var values = Enum.GetValues(type);
var setValues = new List<Enum>();
foreach(var enumValue in values)
{
if (value.HasFlag((Enum)enumValue))
setValues.Add((Enum)enumValue);
}
var stringList = new List<string>();
foreach (var singleValue in setValues)
{
var name = Enum.GetName(type, singleValue);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =
Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
stringList.Add(attr.Description);
}
}
}
}
return string.Join(",", stringList.ToArray());
}
不是最干净的代码,但你明白了,只是记住,对于不是标志的枚举,它不会按预期工作 - 只是抛出一个想法。
在细读了一些关于在 C# 中为枚举值一般创建对友好字符串的访问的常见方法的其他问题后 this answer 似乎是我最好的通用解决方案,其中友好字符串可以放在定义中使用 DescriptionAttribute
s.
我将其实现为扩展方法,但很快意识到它仅适用于未指定 [Flags]
属性的标准枚举。对于存在该属性的情况,我不完全确定执行此操作的最佳方法。
由于 flags 属性意味着可以同时选择多个值,因此使用单个 "friendly string" 没有意义。我正在考虑以相同的方式定义友好的字符串,但是重载扩展方法以采用特定的枚举类型,它会 return a List<string>
为所有选定的值提供友好的字符串。
上述解决方案可行,但我觉得会有很多代码重复,因为每个使用 Flags 属性的枚举都需要它自己的扩展方法,因为枚举只能由 System.Enum
继承,消除了我创建基本类型的能力。如果我能有一个更通用的方法来处理这个问题,如果 flags 属性存在则检查枚举然后 return 以下之一:
- 单个字符串(如果没有 Flags),列表(如果有 Flags)- 签名 returns
object
- 单个字符串(如果没有 Flags),列表(如果有 Flags)- 签名 returns
dynamic
- 如果未指定标志,则可能仅包含一个值的列表 - 签名 returns
List<string>
我觉得这个问题可能是 "having my cake and eating it too" 的情况,因为我宁愿在获取友好字符串并删除代码重复数据后不必进行额外的检查。有没有什么技巧或好方法可以做到这一点而不是乱七八糟的黑客?
使用 enum.ToString()
获取 "unfriendly" 字符串(其中 enum 是您的 Enum 变量)。编写一个可重用的扩展方法,将 UnfriendlyString 转换为友好的 "unfriendly string"(例如,在有大写字母或类似字母的地方插入 space-小写字母)。
对于[Flags]
,您可以Split
不友好的字符串,转换每个子字符串,也许再次Join
;或者您的扩展方法可以考虑逗号。
您可以像 link 的答案一样编写方法,但支持标志枚举和 return 逗号分隔的字符串,例如:
public static string GetDescription(Enum value)
{
Type type = value.GetType();
var values = Enum.GetValues(type);
var setValues = new List<Enum>();
foreach(var enumValue in values)
{
if (value.HasFlag((Enum)enumValue))
setValues.Add((Enum)enumValue);
}
var stringList = new List<string>();
foreach (var singleValue in setValues)
{
var name = Enum.GetName(type, singleValue);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =
Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
stringList.Add(attr.Description);
}
}
}
}
return string.Join(",", stringList.ToArray());
}
不是最干净的代码,但你明白了,只是记住,对于不是标志的枚举,它不会按预期工作 - 只是抛出一个想法。