.net dotnet核心中的枚举描述属性

xwmevbvl  于 2023-10-21  发布在  .NET
关注(0)|答案(6)|浏览(148)

我们在dot net CLI中有枚举的Description属性吗?(网络核心RC2)如果没有,任何替代方案?

brc7rcf0

brc7rcf01#

我不得不修改@yaniv的答案,以使用DescriptionAttribute类型并获取Description字段。

  1. public static class EnumExtensions
  2. {
  3. /// <summary>
  4. /// Get the Description from the DescriptionAttribute.
  5. /// </summary>
  6. /// <param name="enumValue"></param>
  7. /// <returns></returns>
  8. public static string GetDescription(this Enum enumValue)
  9. {
  10. return enumValue.GetType()
  11. .GetMember(enumValue.ToString())
  12. .First()
  13. .GetCustomAttribute<DescriptionAttribute>()?
  14. .Description ?? string.Empty;
  15. }
  16. }
展开查看全部
gab6jxml

gab6jxml2#

对于1.0和1.1,DescriptionAttribute现在在System.ComponentModel.Primitives NuGet包中。

hpxqektj

hpxqektj3#

更新了NET 7+的答案(10/19/2023)
使用NET DescriptionAttribute
使用

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Runtime.CompilerServices;

  1. public static class EnumExtensions
  2. {
  3. private static readonly Dictionary<Type, Dictionary<object, string>> _enumTypeMemberDescriptionCache = new Dictionary<Type, Dictionary<object, string>>();
  4. public static void PreCacheEnumDescriptions(params Type[] scanMarkers)
  5. {
  6. foreach (var scanMarker in scanMarkers)
  7. {
  8. var enumTypes = scanMarker
  9. .Assembly
  10. .ExportedTypes
  11. .Where(x => x.IsEnum);
  12. CacheEnumExportTypes(enumTypes);
  13. }
  14. }
  15. private static void CacheEnumExportTypes(IEnumerable<Type> enumTypes)
  16. {
  17. foreach (var type in enumTypes)
  18. {
  19. if (!type.IsEnum) continue;
  20. CacheEnumMemberDescriptionValues(type);
  21. }
  22. }
  23. private static void CacheEnumMemberDescriptionValues(Type enumType)
  24. {
  25. var enums = Enum.GetValues(enumType);
  26. foreach (Enum enumMember in enums)
  27. {
  28. var enumTypeCached = _enumTypeMemberDescriptionCache.ContainsKey(enumType);
  29. var enumFieldCached = enumTypeCached && _enumTypeMemberDescriptionCache[enumType].ContainsKey(enumMember);
  30. if (enumTypeCached && enumFieldCached)
  31. {
  32. continue;
  33. }
  34. if (!enumTypeCached)
  35. {
  36. _enumTypeMemberDescriptionCache[enumType] = new Dictionary<object, string>();
  37. }
  38. if (!enumFieldCached)
  39. {
  40. _ = FindAndCacheEnumDescription(enumType, enumMember);
  41. }
  42. }
  43. }
  44. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  45. public static string GetDescription<TEnum>(this TEnum enumMember) where TEnum : notnull
  46. {
  47. if (enumMember == null) return null;
  48. var enumType = typeof(TEnum);
  49. var enumTypeCached = _enumTypeMemberDescriptionCache.ContainsKey(enumType);
  50. var enumFieldCached = enumTypeCached && _enumTypeMemberDescriptionCache[enumType].ContainsKey(enumMember);
  51. if (enumTypeCached && enumFieldCached)
  52. {
  53. return _enumTypeMemberDescriptionCache[enumType][enumMember];
  54. }
  55. if (!enumTypeCached)
  56. {
  57. _enumTypeMemberDescriptionCache[enumType] = new Dictionary<object, string>();
  58. }
  59. return FindAndCacheEnumDescription(enumType, enumMember);
  60. }
  61. [MethodImpl(MethodImplOptions.AggressiveOptimization)]
  62. private static string FindAndCacheEnumDescription<TEnum>(Type enumType, TEnum enumMember) where TEnum : notnull
  63. {
  64. var attributes = enumType
  65. .GetField(enumMember.ToString())
  66. ?.GetCustomAttributes(false);
  67. if (attributes != null)
  68. {
  69. foreach (var attribute in attributes.OfType<DescriptionAttribute>())
  70. {
  71. _enumTypeMemberDescriptionCache[enumType][enumMember] = attribute.Description;
  72. return attribute.Description;
  73. }
  74. }
  75. return enumMember.ToString();
  76. }
  77. }

更新增加了基本级别的缓存,删除了动态,还允许OnStart PreCache。非常简单的用法如下

  1. // Give it a Type inside the Assembly to scan for Enums and cache description.
  2. EnumExtensions.PreCacheEnumDescriptions(typeof(StaticClassWithEnums));
  3. // If not pre-cached, first will use light reflection to find Description attribute.
  4. var description = EnumType.EnumMember.GetDescription();
  5. // Second call uses in-memory cached value.
  6. description = EnumType.EnumMember.GetDescription();

Bonus Razor Page/MVC HTML Static Helper
GetEnumSelectListWithDescriptions()的实现

  1. private static readonly Dictionary<Type, IEnumerable<SelectListItem>> _enumSelectListCache = new Dictionary<Type, IEnumerable<SelectListItem>>();
  2. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  3. public static IEnumerable<SelectListItem> GetEnumSelectListWithDescriptions<TEnum>(this IHtmlHelper _)
  4. where TEnum : Enum
  5. {
  6. var enumType = typeof(TEnum);
  7. if (_enumSelectListCache.ContainsKey(enumType))
  8. {
  9. return _enumSelectListCache[enumType];
  10. }
  11. var enumSelectList = Enum
  12. .GetValues(typeof(TEnum))
  13. .OfType<TEnum>()
  14. .Select(
  15. e => new SelectListItem
  16. {
  17. Value = e.ToString(),
  18. Text = e.GetDescription()
  19. });
  20. _enumSelectListCache[enumType] = enumSelectList;
  21. return enumSelectList;
  22. }

原始应答
我在我的Net Framework实现中使用了这个:

  1. public static class EnumerationExtension
  2. {
  3. public static string Description( this Enum value )
  4. {
  5. // get attributes
  6. var field = value.GetType().GetField( value.ToString() );
  7. var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false );
  8. // return description
  9. return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found";
  10. }
  11. }

这对NetCore不起作用,所以我修改了它来做到这一点:

  1. public static class EnumerationExtension
  2. {
  3. public static string Description( this Enum value )
  4. {
  5. // get attributes
  6. var field = value.GetType().GetField( value.ToString() );
  7. var attributes = field.GetCustomAttributes( false );
  8. // Description is in a hidden Attribute class called DisplayAttribute
  9. // Not to be confused with DisplayNameAttribute
  10. dynamic displayAttribute = null;
  11. if (attributes.Any())
  12. {
  13. displayAttribute = attributes.ElementAt( 0 );
  14. }
  15. // return description
  16. return displayAttribute?.Description ?? "Description Not Found";
  17. }
  18. }

枚举示例:

  1. public enum ExportTypes
  2. {
  3. [Display( Name = "csv", Description = "text/csv" )]
  4. CSV = 0
  5. }

添加了任一静态的示例用法:

  1. var myDescription = myEnum.Description();
展开查看全部
zxlwwiss

zxlwwiss4#

DescriptionAttribute was added to CoreFX,但仅在RC2之后。所以它将在RTM版本中出现,但不在RC2中。根据您想要做的事情,创建自己的属性可能会起作用。

pprl5pva

pprl5pva5#

您可以使用“DisplayAttribute”并执行

  1. public static string Description(this Enum enumValue)
  2. {
  3. return enumValue.GetType()
  4. .GetMember(enumValue.ToString())
  5. .First()
  6. .GetCustomAttribute<DisplayAttribute>()
  7. .GetDescription();
  8. }
7rtdyuoh

7rtdyuoh6#

为了避免按照@pamcevoj的回答使用System.Reflection和按照@HouseCat的回答使用dynamic,我在@HouseCat的解决方案上构建了.NET Core 3.1中的这个解决方案

  1. public static string Description(this Enum enumValue)
  2. {
  3. var descriptionAttribute = enumValue.GetType()
  4. .GetField(enumValue.ToString())
  5. .GetCustomAttributes(false)
  6. .SingleOrDefault(attr => attr.GetType() == typeof(DescriptionAttribute)) as DescriptionAttribute;
  7. // return description
  8. return descriptionAttribute?.Description ?? "";
  9. }

相关问题