【问题标题】:Get Description Attributes From a Flagged Enum从标记的枚举中获取描述属性
【发布时间】:2018-01-07 15:19:24
【问题描述】:

我正在尝试创建一个扩展方法,它将返回一个 List<string>,其中包含所有 Description 属性,仅用于给定 [Flags] Enum 的设置值。

例如,假设我在 C# 代码中声明了以下枚举:

[Flags]
public enum Result
{
    [Description("Value 1 with spaces")]
    Value1 = 1,
    [Description("Value 2 with spaces")]
    Value2 = 2,
    [Description("Value 3 with spaces")]
    Value3 = 4,
    [Description("Value 4 with spaces")]
    Value4 = 8
}

然后将变量设置为:

Result y = Result.Value1 | Result.Value2 | Result.Value4;

所以,我要创建的调用是:

List<string> descriptions = y.GetDescriptions();

最终的结果是:

descriptions = { "Value 1 with spaces", "Value 2 with spaces", "Value 4 with spaces" };

我创建了一个扩展方法,用于为不能设置多个标志的枚举获取 单个描述属性,如下所示:

public static string GetDescription(this Enum value)
{
    Type type = value.GetType();
    string name = Enum.GetName(type, value);
    if (name != null)
    {
        System.Reflection.FieldInfo field = type.GetField(name);
        if (field != null)
        {
            DescriptionAttribute attr =
                   Attribute.GetCustomAttribute(field,
                     typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attr != null)
            {
                return attr.Description;
            }
        }
    }
    return null;
}

我在网上找到了一些关于如何获取给定枚举类型(例如here)的所有描述属性的答案,但是我在编写通用扩展方法以返回描述列表时遇到问题仅用于设置的属性。

任何帮助将不胜感激。

谢谢!!

【问题讨论】:

  • 我编辑了你的标题,因为当你使用 C#时你的问题不是about C#(你的标题中没有必要有标签,除非它是它的一个组成部分)
  • @slugster,我把它放在我的标题中,因为我想提到它是 ac# 问题而不是 Java / 其他语言 - 我正在寻找一种用特定语言编写的扩展方法,所以我觉得合适。

标签: c# reflection enums system.componentmodel


【解决方案1】:

HasFlag 是你的朋友。 :-)

下面的扩展方法使用您在上面发布的 GetDescription 扩展方法,因此请确保您拥有它。然后应该可以使用以下方法:

public static List<string> GetDescriptionsAsText(this Enum yourEnum)
{       
    List<string> descriptions = new List<string>();

    foreach (Enum enumValue in Enum.GetValues(yourEnum.GetType()))
    {
        if (yourEnum.HasFlag(enumValue))
        {
            descriptions.Add(enumValue.GetDescription());
        }
    }

    return descriptions;
}

注意HasFlag 允许您将给定的 Enum 值与定义的标志进行比较。在您的示例中,如果您有

Result y = Result.Value1 | Result.Value2 | Result.Value4;

然后

y.HasFlag(Result.Value1)

应该是真的,而

y.HasFlag(Result.Value3)

会是假的。

另请参阅:https://msdn.microsoft.com/en-us/library/system.enum.hasflag(v=vs.110).aspx

【讨论】:

  • 该死!! - 我是如此接近! - 非常感谢你结束了我的痛苦!! :)
  • 很高兴为您提供帮助。我现在也更新了 foreach 变量的名称——让它感觉更通用一点(带有一个小的“g”)。不会改变任何东西 - 只是看起来更整洁。
【解决方案2】:

这是一个使用 LINQ 的紧凑型解决方案,它还会检查 null,以防并非所有值都有属性:

public static List<T> GetFlagEnumAttributes<T>(this Enum flagEnum) where T : Attribute
{
   var type = flagEnum.GetType();
   return Enum.GetValues(type)
      .Cast<Enum>()
      .Where(flagEnum.HasFlag)
      .Select(e => type.GetMember(e.ToString()).First())
      .Select(info => info.GetCustomAttribute<T>())
      .Where(attribute => attribute != null)
      .ToList();
}

【讨论】:

    【解决方案3】:

    您可以从枚举中迭代所有值,然后过滤它们不包含在您的输入值中。

        public static List<T> GetAttributesByFlags<T>(this Enum arg) where T: Attribute
        {
            var type = arg.GetType();
            var result = new List<T>();
            foreach (var item in Enum.GetValues(type))
            {
                var value = (Enum)item;
                if (arg.HasFlag(value)) // it means that '(arg & value) == value'
                {
                    var memInfo = type.GetMember(value.ToString())[0];
                    result.Add((T)memInfo.GetCustomAttribute(typeof(T), false));
                }
            }
            return result;
        }
    

    你会得到你想要的属性列表:

    var arg = Result.Value1 | Result.Value4;
    List<DescriptionAttribute> attributes = arg.GetAttributesByFlags<DescriptionAttribute>();
    

    【讨论】:

      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 2013-02-19
      • 1970-01-01
      相关资源
      最近更新 更多