属性辅助方法的 c# 泛型

我找不到在 .Net Core 中实现此 DRY 的好方法。(不要重复自己)。我怎样才能做到不重复大部分逻辑?以下是 2 种方法:


    public static string GetCategory(this Enum val)

    {

        CategoryAttribute[] attributes = (CategoryAttribute[])val

            .GetType()

            .GetField(val.ToString())

            .GetCustomAttributes(typeof(CategoryAttribute), false);

        return attributes.Length > 0 ? attributes[0].Category : string.Empty;

    }



    public static string GetDescription(this Enum val)

    {

        DescriptionAttribute[] attributes = (DescriptionAttribute[])val

            .GetType()

            .GetField(val.ToString())

            .GetCustomAttributes(typeof(DescriptionAttribute), false);

        return attributes.Length > 0 ? attributes[0].Description : string.Empty;

    }


森林海
浏览 144回答 3
3回答

扬帆大鱼

我会从这个开始:public static T GetAttribute<T>(this Enum val)&nbsp; &nbsp; where T : Attribute{&nbsp; &nbsp; return (T)val&nbsp; &nbsp; .GetType()&nbsp; &nbsp; .GetField(val.ToString())&nbsp; &nbsp; .GetCustomAttribute(typeof(T), false);}将您的方法变成这样:public static string GetCategory(this Enum val){&nbsp; &nbsp; return val.GetAttribute<CategoryAttribute>()?.Category ?? string.Empty;}public static string GetDescription(this Enum val){&nbsp; &nbsp; return val.GetAttribute<DescriptionAttribute>()?.Description ?? string.Empty;}可以说你可以做更多的事情来让那些最终的方法更干一点,但我猜你在这里使用的模式(从属性中获取属性并返回它的值或空字符串)可能不够普遍值得专门为此创建一个方法。GetAttribute另一方面,该方法可能具有更高的可重用性。

牛魔王的故事

您可以使用GetCustomAttribute<T>instead 的通用版本,它可以将代码简化到不需要 IMO 的另一个抽象的地方。public static string GetCategory(this Enum val){&nbsp; &nbsp; return val.GetType()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetField(val.ToString())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetCustomAttribute<CategoryAttribute>(false)?.Category ?? string.Empty;}public static string GetDescription(this Enum val){&nbsp; &nbsp; return val.GetType()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetField(val.ToString())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetCustomAttribute<DescriptionAttribute>(false)?.Description ?? string.Empty;}

波斯汪

在 C# 7.3 中,您可以将方法限制为枚举类型。这将为您节省一箱枚举。public static class AttributeExtensions{&nbsp; &nbsp; public static string GetCategory<T>(this T val) where T: Enum&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return GetAttr<CategoryAttribute, T>(val)?.Category ?? "";&nbsp; &nbsp; }&nbsp; &nbsp; public static string GetDescription<T>(this T val) where T : Enum&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return GetAttr<DescriptionAttribute, T>(val)?.Description ?? "";&nbsp; &nbsp; }&nbsp; &nbsp; private static TAttr GetAttr<TAttr, T>(this T val) where TAttr : Attribute&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (TAttr)typeof(T)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetField(val.ToString())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ?.GetCustomAttributes(typeof(TAttr), false)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ?.FirstOrDefault();&nbsp; &nbsp; }}此外,在使用反射时,缓存性能很重要:public static class AttributeExtensions{&nbsp; &nbsp; private class EnumMetadata&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public CategoryAttribute CategoryAttribute { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public DescriptionAttribute DescriptionAttribute { get; set; }&nbsp; &nbsp; }&nbsp; &nbsp; private class EnumMetadataCache<T> where T : Enum&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; private static readonly ConcurrentDictionary<T, EnumMetadata> MetadataCache = new ConcurrentDictionary<T, EnumMetadata>();&nbsp; &nbsp; &nbsp; &nbsp; public static EnumMetadata GetMetadata(T item)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return MetadataCache.GetOrAdd(item, val =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new EnumMetadata&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CategoryAttribute = GetAttr<CategoryAttribute, T>(val),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DescriptionAttribute = GetAttr<DescriptionAttribute, T>(val)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public static string GetCategory<T>(this T val) where T : Enum&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return EnumMetadataCache<T>.GetMetadata(val).CategoryAttribute?.Category ?? "";&nbsp; &nbsp; }&nbsp; &nbsp; public static string GetDescription<T>(this T val) where T : Enum&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return EnumMetadataCache<T>.GetMetadata(val).DescriptionAttribute?.Description ?? "";&nbsp; &nbsp; }&nbsp; &nbsp; private static TAttr GetAttr<TAttr, T>(this T val) where TAttr : Attribute&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (TAttr)typeof(T)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetField(val.ToString())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ?.GetCustomAttributes(typeof(TAttr), false)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ?.FirstOrDefault();&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP