在C#中使用Attributes(特性)来控制枚举成员是否应该被序列化或映射

如果标记了[NonSerialized]特性,会防止将该字段序列化。但是,该字段仍然可以用于foreach迭代,因为它仍然是枚举的有效成员。
如果要防止特定枚举成员被foreach迭代,用[NonSerialized]特性是不起作用的。相反,可以创建一个自定义的Attribute继承自System.Attribute,并将其应用到需要隐藏的枚举成员上。在枚举上使用[Flags]特性也将防止它被foreach迭代。
以下是一个示例,防止枚举成员被foreach迭代:

[Flags]
public enum SampleEnum
{
    abc,
    def,
    [EnumIteratorIgnore]
    efg
}

[AttributeUsage(AttributeTargets.Field)]
public class EnumIteratorIgnoreAttribute : Attribute { }
foreach (SampleEnum e in Enum.GetValues(typeof(SampleEnum)))
{
    if (e.GetType()
         .GetField(Enum.GetName(typeof(SampleEnum), e))
         .GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true)
         .Length == 0)
    {
        yield return e;
    }
}
// 添加 ? 协定后缀
foreach (SampleEnum? e in Enum.GetValues(typeof(SampleEnum)))
{
    if (e?.GetType()        // 使用 ?. 运算符
          .GetField(e.Value.ToString())
          .GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true)
          .Length == 0)
    {
        yield return e.Value;
    }
}

在这个示例中,SampleEnum类型被标记为[Flags],这意味着它是一个位标记,不能直接用于foreach迭代。此外,egf枚举成员上定义了一个自定义的EnumIteratorIgnoreAttribute特性,该特性将防止该成员被迭代。
在枚举类型上定义了一个GetEnumValues()方法,该方法遍历枚举类型的所有值,并使用反射来查找每个值的自定义特性。如果枚举值上未发现EnumIteratorIgnoreAttribute特性,则枚举值将被yield返回,否则将被忽略。
因此,在foreach循环中使用GetEnumValues()方法来获取枚举类型的所有值,而忽略在枚举成员上定义了EnumIteratorIgnoreAttribute特性的值。

第三种:
 Enum.GetValues<SampleEnum>().ToList().ForEach(item => {
                if (item!.GetType()!.GetField(item.ToString()!)!.GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true).Length == 0)
                {
                    Console.WriteLine(item.ToString());
                }
            });

 

posted @ 2023-04-12 14:06  Tammytan  阅读(143)  评论(0编辑  收藏  举报