繁体   English   中英

如何获取已用特定属性修饰的枚举成员列表

[英]How to get a list of enum members that have been decorated with specific attribute

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

我怎么能这样做?

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

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

    [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);
    }

每当您使用属性时,您都必须使用反射。 混合一些 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")))

您可以为此使用反射

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM