属性助手方法的c#泛型
我找不到一个好方法使这个在.Net内核中干燥。(不要重复)。我怎样才能做到不重复大部分逻辑?以下是两种方法:属性助手方法的c#泛型,c#,generics,.net-core,C#,Generics,.net Core,我找不到一个好方法使这个在.Net内核中干燥。(不要重复)。我怎样才能做到不重复大部分逻辑?以下是两种方法: public static string GetCategory(this Enum val) { CategoryAttribute[] attributes = (CategoryAttribute[])val .GetType() .GetField(val.ToString())
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;
}
您可以使用的泛型版本,它将代码简化到不需要另一个抽象的地方
public static string GetCategory(this Enum val)
{
return val.GetType()
.GetField(val.ToString())
.GetCustomAttribute<CategoryAttribute>(false)?.Category ?? string.Empty;
}
public static string GetDescription(this Enum val)
{
return val.GetType()
.GetField(val.ToString())
.GetCustomAttribute<DescriptionAttribute>(false)?.Description ?? string.Empty;
}
公共静态字符串GetCategory(此枚举值)
{
return val.GetType()
.GetField(val.ToString())
.GetCustomAttribute(false)?.Category?字符串。空;
}
公共静态字符串GetDescription(此枚举值)
{
return val.GetType()
.GetField(val.ToString())
.GetCustomAttribute(false)?.Description??字符串。空;
}
我首先要说:
public static T GetAttribute<T>(this Enum val)
where T : Attribute
{
return (T)val
.GetType()
.GetField(val.ToString())
.GetCustomAttribute(typeof(T), false);
}
publicstatict GetAttribute(此枚举值)
其中T:Attribute
{
返回(T)值
.GetType()
.GetField(val.ToString())
.GetCustomAttribute(typeof(T),false);
}
将您的方法转化为:
public static string GetCategory(this Enum val)
{
return val.GetAttribute<CategoryAttribute>()?.Category ?? string.Empty;
}
public static string GetDescription(this Enum val)
{
return val.GetAttribute<DescriptionAttribute>()?.Description ?? string.Empty;
}
公共静态字符串GetCategory(此枚举值)
{
返回val.GetAttribute()?.Category??string.Empty;
}
公共静态字符串GetDescription(此枚举值)
{
返回val.GetAttribute()?.Description??string.Empty;
}
可以说,您可以做更多的工作来让这些最终方法变得更加干燥,但我猜您在这里使用的模式(从属性获取属性并返回其值或空字符串)可能不够常见,不值得专门为此创建一个方法。另一方面,GetAttribute
方法可能更易于重用。在C#7.3中,可以将方法约束为枚举类型。
这将为您节省枚举的一个装箱
public static class AttributeExtensions
{
public static string GetCategory<T>(this T val) where T: Enum
{
return GetAttr<CategoryAttribute, T>(val)?.Category ?? "";
}
public static string GetDescription<T>(this T val) where T : Enum
{
return GetAttr<DescriptionAttribute, T>(val)?.Description ?? "";
}
private static TAttr GetAttr<TAttr, T>(this T val) where TAttr : Attribute
{
return (TAttr)typeof(T)
.GetField(val.ToString())
?.GetCustomAttributes(typeof(TAttr), false)
?.FirstOrDefault();
}
}
公共静态类属性扩展
{
公共静态字符串GetCategory(此T val),其中T:Enum
{
返回GetAttr(val)?.Category;
}
公共静态字符串GetDescription(此T val),其中T:Enum
{
返回GetAttr(val)?.Description;
}
私有静态TAttr GetAttr(此T val),其中TAttr:Attribute
{
返回(TAttr)类型(T)
.GetField(val.ToString())
?GetCustomAttributes(typeof(TAttr),false)
?.FirstOrDefault();
}
}
此外,在使用反射时,缓存以提高性能也很重要:
public static class AttributeExtensions
{
private class EnumMetadata
{
public CategoryAttribute CategoryAttribute { get; set; }
public DescriptionAttribute DescriptionAttribute { get; set; }
}
private class EnumMetadataCache<T> where T : Enum
{
private static readonly ConcurrentDictionary<T, EnumMetadata> MetadataCache = new ConcurrentDictionary<T, EnumMetadata>();
public static EnumMetadata GetMetadata(T item)
{
return MetadataCache.GetOrAdd(item, val =>
new EnumMetadata
{
CategoryAttribute = GetAttr<CategoryAttribute, T>(val),
DescriptionAttribute = GetAttr<DescriptionAttribute, T>(val)
}
);
}
}
public static string GetCategory<T>(this T val) where T : Enum
{
return EnumMetadataCache<T>.GetMetadata(val).CategoryAttribute?.Category ?? "";
}
public static string GetDescription<T>(this T val) where T : Enum
{
return EnumMetadataCache<T>.GetMetadata(val).DescriptionAttribute?.Description ?? "";
}
private static TAttr GetAttr<TAttr, T>(this T val) where TAttr : Attribute
{
return (TAttr)typeof(T)
.GetField(val.ToString())
?.GetCustomAttributes(typeof(TAttr), false)
?.FirstOrDefault();
}
}
公共静态类属性扩展
{
私有类枚举元数据
{
公共类别属性类别属性{get;set;}
公共描述符属性描述符属性{get;set;}
}
私有类EnumMetadataCache,其中T:Enum
{
私有静态只读ConcurrentDictionary MetadataCache=新ConcurrentDictionary();
公共静态枚举元数据GetMetadata(T项)
{
返回MetadataCache.GetOrAdd(项,val=>
新枚举元数据
{
CategoryAttribute=GetAttr(val),
DescriptionAttribute=GetAttr(val)
}
);
}
}
公共静态字符串GetCategory(此T val),其中T:Enum
{
返回EnumMetadataCache.GetMetadata(val.CategoryAttribute?.Category??”;
}
公共静态字符串GetDescription(此T val),其中T:Enum
{
返回EnumMetadataCache.GetMetadata(val.DescriptionAttribute?.Description??”;
}
私有静态TAttr GetAttr(此T val),其中TAttr:Attribute
{
返回(TAttr)类型(T)
.GetField(val.ToString())
?GetCustomAttributes(typeof(TAttr),false)
?.FirstOrDefault();
}
}
这是.NET Framework还是.NET Standard/Core?用TAttribute
type参数替换属性类型。将访问器Func作为参数添加到帮助器中,而不是尝试直接检索属性,例如调用helper@Haytam这是.net核心。…这是.net核心。
这已经干了。但是,我喜欢下面发布的StriplingWarrior的答案。记住将false
传递到该方法中,以保持OP的行为。谢谢@Igor。我打算用这个答案。如果添加另一个helper方法,则其所需的代码将更少。你的回答也是正确的。