【问题标题】:How to get a list of enum members that have been decorated with specific attribute如何获取已用特定属性修饰的枚举成员列表
【发布时间】:2020-05-03 21:16:12
【问题描述】:

我想返回具有特定属性的枚举成员列表。所以对于代码示例,我想要一个包含枚举 SecondValue 和 ThirdValue 的列表,但不是 FirstValue 或 FourthValue,因为它没有属性 Container。

我该怎么做?

PS:这之前被标记为重复,并带有指向此的链接: Getting attributes of Enum's value

这不是同一个问题。我制作了更多示例代码以使我的问题更清楚。查看函数定义及其应返回的内容。

    [AttributeUsage(AttributeTargets.Field)]
    public sealed class ContainerAttribute : Attribute
    {
        public string Name { get; }

        public ContainerAttribute(string name)
        {
            Name = name;
        }
    }

    public enum MyEnum
    {
        [SomeOtherAttribute("attr")]
        FirstValue,

        [Container("name1")]
        SecondValue,

        [Container("name1")]
        ThirdValue,

        FourthValue
    }

    public List<MyEnum> GetEnumsWithAttribute(Attribute value) { }

    public void Main(String[] args) { 
       // someEnums should return list with content: [MyEnum.SecondValue, MyEnum.ThirdValue];
       var someEnums = GetEnumsWithAttribute(ContainerAttribute);
    }

【问题讨论】:

  • 您的实际代码是什么?您尝试过什么来实现这一目标?

标签: c# .net enums


【解决方案1】:

每当您使用属性时,您都必须使用反射。混合一些 Linq,您可以检查枚举的字段以按属性类型过滤,然后从字段名称解析结果。

Type ta = typeof(ContainerAttribute);
Type t = typeof(MyEnum);

var result = t.GetFields()
    .Where(a => a.CustomAttributes.Any(c => c.AttributeType == ta))
    .Select(a => (MyEnum)Enum.Parse(t, a.Name))
    .ToList();

更新

虽然您的问题不清楚您是否需要通过Name 进一步过滤,但 Guru 的回答暗示您可能会这样做,或者将来会这样做。如果是这样,您可以通过更改 Where 子句来编辑我的解决方案以接受您想要的 Name 字符串:

// method would take a string argument rather than hard-coding "name1"
.Where(a => a.CustomAttributes.Any(c => c.AttributeType == ta && c.ConstructorArguments.Any(ca => ca.Value.ToString() == "name1")))

【讨论】:

    【解决方案2】:

    您可以为此使用reflection

    public static List<MyEnum> GetEnumsWithAttribute(Attribute value)
        {
            return typeof(MyEnum)
               .GetMembers()
               .Where(m => m.MemberType == MemberTypes.Field)
               .Where(m => m.GetCustomAttributes().Any(a => a.Equals(value)))
               .Select(m => Enum.Parse<MyEnum>(m.Name))
               .ToList();
        }
    

    此实现依赖于 .EqualsContainerAttribute 中重载,如下所示:

    public override bool Equals(object? obj)
            {
                var other = obj as ContainerAttribute;
                if (other == null) return false;
                return this.Name == other.Name;
            }
    

    如果您不想覆盖Equals,您可以将您的方法更改为通用:

        public static List<MyEnum> GetEnumsWithAttribute<T>(T value, Func<T, T , bool> comparerFunc) where T: Attribute
        {
            return typeof(MyEnum)
               .GetMembers()
               .Where(m => m.MemberType == MemberTypes.Field)
               .Where(m => m.GetCustomAttributes().Any(a => a is T && comparerFunc((T)a, value)))
               .Select(m => Enum.Parse<MyEnum>(m.Name))
               .ToList();
        }
    

    及用法:

    var someEnums = GetEnumsWithAttribute(new ContainerAttribute("name1"), (a1, a2) => a1.Name == a2.Name);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-27
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      • 2011-02-16
      • 2011-07-03
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多