我们在dot net CLI中有枚举的Description属性吗?(网络核心RC2)如果没有,任何替代方案?
Description
brc7rcf01#
我不得不修改@yaniv的答案,以使用DescriptionAttribute类型并获取Description字段。
DescriptionAttribute
public static class EnumExtensions{ /// <summary> /// Get the Description from the DescriptionAttribute. /// </summary> /// <param name="enumValue"></param> /// <returns></returns> public static string GetDescription(this Enum enumValue) { return enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DescriptionAttribute>()? .Description ?? string.Empty; }}
public static class EnumExtensions
{
/// <summary>
/// Get the Description from the DescriptionAttribute.
/// </summary>
/// <param name="enumValue"></param>
/// <returns></returns>
public static string GetDescription(this Enum enumValue)
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DescriptionAttribute>()?
.Description ?? string.Empty;
}
gab6jxml2#
对于1.0和1.1,DescriptionAttribute现在在System.ComponentModel.Primitives NuGet包中。
System.ComponentModel.Primitives
hpxqektj3#
更新了NET 7+的答案(10/19/2023)使用NET DescriptionAttribute使用
using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Runtime.CompilerServices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
类
public static class EnumExtensions{ private static readonly Dictionary<Type, Dictionary<object, string>> _enumTypeMemberDescriptionCache = new Dictionary<Type, Dictionary<object, string>>(); public static void PreCacheEnumDescriptions(params Type[] scanMarkers) { foreach (var scanMarker in scanMarkers) { var enumTypes = scanMarker .Assembly .ExportedTypes .Where(x => x.IsEnum); CacheEnumExportTypes(enumTypes); } } private static void CacheEnumExportTypes(IEnumerable<Type> enumTypes) { foreach (var type in enumTypes) { if (!type.IsEnum) continue; CacheEnumMemberDescriptionValues(type); } } private static void CacheEnumMemberDescriptionValues(Type enumType) { var enums = Enum.GetValues(enumType); foreach (Enum enumMember in enums) { var enumTypeCached = _enumTypeMemberDescriptionCache.ContainsKey(enumType); var enumFieldCached = enumTypeCached && _enumTypeMemberDescriptionCache[enumType].ContainsKey(enumMember); if (enumTypeCached && enumFieldCached) { continue; } if (!enumTypeCached) { _enumTypeMemberDescriptionCache[enumType] = new Dictionary<object, string>(); } if (!enumFieldCached) { _ = FindAndCacheEnumDescription(enumType, enumMember); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string GetDescription<TEnum>(this TEnum enumMember) where TEnum : notnull { if (enumMember == null) return null; var enumType = typeof(TEnum); var enumTypeCached = _enumTypeMemberDescriptionCache.ContainsKey(enumType); var enumFieldCached = enumTypeCached && _enumTypeMemberDescriptionCache[enumType].ContainsKey(enumMember); if (enumTypeCached && enumFieldCached) { return _enumTypeMemberDescriptionCache[enumType][enumMember]; } if (!enumTypeCached) { _enumTypeMemberDescriptionCache[enumType] = new Dictionary<object, string>(); } return FindAndCacheEnumDescription(enumType, enumMember); } [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static string FindAndCacheEnumDescription<TEnum>(Type enumType, TEnum enumMember) where TEnum : notnull { var attributes = enumType .GetField(enumMember.ToString()) ?.GetCustomAttributes(false); if (attributes != null) { foreach (var attribute in attributes.OfType<DescriptionAttribute>()) { _enumTypeMemberDescriptionCache[enumType][enumMember] = attribute.Description; return attribute.Description; } } return enumMember.ToString(); }}
private static readonly Dictionary<Type, Dictionary<object, string>> _enumTypeMemberDescriptionCache = new Dictionary<Type, Dictionary<object, string>>();
public static void PreCacheEnumDescriptions(params Type[] scanMarkers)
foreach (var scanMarker in scanMarkers)
var enumTypes = scanMarker
.Assembly
.ExportedTypes
.Where(x => x.IsEnum);
CacheEnumExportTypes(enumTypes);
private static void CacheEnumExportTypes(IEnumerable<Type> enumTypes)
foreach (var type in enumTypes)
if (!type.IsEnum) continue;
CacheEnumMemberDescriptionValues(type);
private static void CacheEnumMemberDescriptionValues(Type enumType)
var enums = Enum.GetValues(enumType);
foreach (Enum enumMember in enums)
var enumTypeCached = _enumTypeMemberDescriptionCache.ContainsKey(enumType);
var enumFieldCached = enumTypeCached && _enumTypeMemberDescriptionCache[enumType].ContainsKey(enumMember);
if (enumTypeCached && enumFieldCached)
continue;
if (!enumTypeCached)
_enumTypeMemberDescriptionCache[enumType] = new Dictionary<object, string>();
if (!enumFieldCached)
_ = FindAndCacheEnumDescription(enumType, enumMember);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetDescription<TEnum>(this TEnum enumMember) where TEnum : notnull
if (enumMember == null) return null;
var enumType = typeof(TEnum);
return _enumTypeMemberDescriptionCache[enumType][enumMember];
return FindAndCacheEnumDescription(enumType, enumMember);
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static string FindAndCacheEnumDescription<TEnum>(Type enumType, TEnum enumMember) where TEnum : notnull
var attributes = enumType
.GetField(enumMember.ToString())
?.GetCustomAttributes(false);
if (attributes != null)
foreach (var attribute in attributes.OfType<DescriptionAttribute>())
_enumTypeMemberDescriptionCache[enumType][enumMember] = attribute.Description;
return attribute.Description;
return enumMember.ToString();
更新增加了基本级别的缓存,删除了动态,还允许OnStart PreCache。非常简单的用法如下
// Give it a Type inside the Assembly to scan for Enums and cache description.EnumExtensions.PreCacheEnumDescriptions(typeof(StaticClassWithEnums));// If not pre-cached, first will use light reflection to find Description attribute.var description = EnumType.EnumMember.GetDescription();// Second call uses in-memory cached value.description = EnumType.EnumMember.GetDescription();
// Give it a Type inside the Assembly to scan for Enums and cache description.
EnumExtensions.PreCacheEnumDescriptions(typeof(StaticClassWithEnums));
// If not pre-cached, first will use light reflection to find Description attribute.
var description = EnumType.EnumMember.GetDescription();
// Second call uses in-memory cached value.
description = EnumType.EnumMember.GetDescription();
Bonus Razor Page/MVC HTML Static HelperGetEnumSelectListWithDescriptions()的实现
GetEnumSelectListWithDescriptions()
private static readonly Dictionary<Type, IEnumerable<SelectListItem>> _enumSelectListCache = new Dictionary<Type, IEnumerable<SelectListItem>>();[MethodImpl(MethodImplOptions.AggressiveInlining)]public static IEnumerable<SelectListItem> GetEnumSelectListWithDescriptions<TEnum>(this IHtmlHelper _) where TEnum : Enum{ var enumType = typeof(TEnum); if (_enumSelectListCache.ContainsKey(enumType)) { return _enumSelectListCache[enumType]; } var enumSelectList = Enum .GetValues(typeof(TEnum)) .OfType<TEnum>() .Select( e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() }); _enumSelectListCache[enumType] = enumSelectList; return enumSelectList;}
private static readonly Dictionary<Type, IEnumerable<SelectListItem>> _enumSelectListCache = new Dictionary<Type, IEnumerable<SelectListItem>>();
public static IEnumerable<SelectListItem> GetEnumSelectListWithDescriptions<TEnum>(this IHtmlHelper _)
where TEnum : Enum
if (_enumSelectListCache.ContainsKey(enumType))
return _enumSelectListCache[enumType];
var enumSelectList = Enum
.GetValues(typeof(TEnum))
.OfType<TEnum>()
.Select(
e => new SelectListItem
Value = e.ToString(),
Text = e.GetDescription()
});
_enumSelectListCache[enumType] = enumSelectList;
return enumSelectList;
原始应答我在我的Net Framework实现中使用了这个:
public static class EnumerationExtension{ public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false ); // return description return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found"; }}
public static class EnumerationExtension
public static string Description( this Enum value )
// get attributes
var field = value.GetType().GetField( value.ToString() );
var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false );
// return description
return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found";
这对NetCore不起作用,所以我修改了它来做到这一点:
public static class EnumerationExtension{ public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( false ); // Description is in a hidden Attribute class called DisplayAttribute // Not to be confused with DisplayNameAttribute dynamic displayAttribute = null; if (attributes.Any()) { displayAttribute = attributes.ElementAt( 0 ); } // return description return displayAttribute?.Description ?? "Description Not Found"; }}
var attributes = field.GetCustomAttributes( false );
// Description is in a hidden Attribute class called DisplayAttribute
// Not to be confused with DisplayNameAttribute
dynamic displayAttribute = null;
if (attributes.Any())
displayAttribute = attributes.ElementAt( 0 );
return displayAttribute?.Description ?? "Description Not Found";
枚举示例:
public enum ExportTypes{ [Display( Name = "csv", Description = "text/csv" )] CSV = 0}
public enum ExportTypes
[Display( Name = "csv", Description = "text/csv" )]
CSV = 0
添加了任一静态的示例用法:
var myDescription = myEnum.Description();
zxlwwiss4#
DescriptionAttribute was added to CoreFX,但仅在RC2之后。所以它将在RTM版本中出现,但不在RC2中。根据您想要做的事情,创建自己的属性可能会起作用。
pprl5pva5#
您可以使用“DisplayAttribute”并执行
public static string Description(this Enum enumValue) { return enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>() .GetDescription(); }
public static string Description(this Enum enumValue)
.GetCustomAttribute<DisplayAttribute>()
.GetDescription();
7rtdyuoh6#
为了避免按照@pamcevoj的回答使用System.Reflection和按照@HouseCat的回答使用dynamic,我在@HouseCat的解决方案上构建了.NET Core 3.1中的这个解决方案
public static string Description(this Enum enumValue) { var descriptionAttribute = enumValue.GetType() .GetField(enumValue.ToString()) .GetCustomAttributes(false) .SingleOrDefault(attr => attr.GetType() == typeof(DescriptionAttribute)) as DescriptionAttribute; // return description return descriptionAttribute?.Description ?? ""; }
var descriptionAttribute = enumValue.GetType()
.GetField(enumValue.ToString())
.GetCustomAttributes(false)
.SingleOrDefault(attr => attr.GetType() == typeof(DescriptionAttribute)) as DescriptionAttribute;
return descriptionAttribute?.Description ?? "";
6条答案
按热度按时间brc7rcf01#
我不得不修改@yaniv的答案,以使用
DescriptionAttribute
类型并获取Description
字段。gab6jxml2#
对于1.0和1.1,
DescriptionAttribute
现在在System.ComponentModel.Primitives
NuGet包中。hpxqektj3#
更新了NET 7+的答案(10/19/2023)
使用NET
DescriptionAttribute
使用
类
更新增加了基本级别的缓存,删除了动态,还允许OnStart PreCache。非常简单的用法如下
Bonus Razor Page/MVC HTML Static Helper
GetEnumSelectListWithDescriptions()
的实现原始应答
我在我的Net Framework实现中使用了这个:
这对NetCore不起作用,所以我修改了它来做到这一点:
枚举示例:
添加了任一静态的示例用法:
zxlwwiss4#
DescriptionAttribute
was added to CoreFX,但仅在RC2之后。所以它将在RTM版本中出现,但不在RC2中。根据您想要做的事情,创建自己的属性可能会起作用。pprl5pva5#
您可以使用“DisplayAttribute”并执行
7rtdyuoh6#
为了避免按照@pamcevoj的回答使用System.Reflection和按照@HouseCat的回答使用dynamic,我在@HouseCat的解决方案上构建了.NET Core 3.1中的这个解决方案