.NET?Core?特性(Attribute)底層原理解析
Attribute的使用場(chǎng)景
Attribute不僅僅局限于C#中,在整個(gè).NET框架中都提供了非常大的拓展點(diǎn),任何地方都有Attribute的影子
- 編譯器層
比如 Obsolete,Conditional - C#層
GET,POST,Max,Range,Require - CLR VM層
StructLayout,DllImport - JIT 層
MethodImpl
Attribute在C#中的調(diào)用
舉個(gè)常用的例子,讀取枚舉上的自定義特性。
public enum Test
{
[EnumDescription("hhhhhh")]
None = 0,
[EnumDescription("xxxxxx")]
Done =1
}
private static IEnumerable<string> GetEnumDescriptions(this Enum e)
{
IEnumerable<string> result = null;
var type = e.GetType();
var fieldInfo = type.GetField(e.ToString());
var attr = fieldInfo?.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);
if (attr?.Length > 0)
{
result = attr.Cast<EnumDescriptionAttribute>().Select(x => x.Description);
}
return result ?? Enumerable.Empty<string>();
}可以看到,Attribute底層在C#中實(shí)現(xiàn)依舊是依賴反射,所以為什么說Attribute是寫給代碼看的注釋,因此對(duì)反射的優(yōu)化思路也可以用在Attribute中。
比如在代碼中,使用Dictionary緩存結(jié)果集。避免過多調(diào)用反射造成的性能問題。
private static IEnumerable<string> GetEnumDescriptionsCache(this Enum e)
{
var key = $"{e.GetType().Name}_{e.ToString()}";
if (_enumMap.ContainsKey(key))
{
return _enumMap[key];
}
else
{
var result = GetEnumDescriptions(e);
_enumMap.TryAdd(key, result);
return result;
}
}循環(huán)100000次造成的性能差距還是很明顯的

Newtonsoft.Json對(duì)Attrubute的使用
以JsonConverter為藍(lán)本舉例說明。
public class Person
{
[JsonConverter(typeof(DateTimeConverter))]
public DateTime CreateTime { get; set; }
}
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.Value == null)
return DateTime.MinValue;
if (DateTime.TryParse(reader.Value.ToString(), out DateTime result))
return result;
return DateTime.MinValue;
}
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
}
}定義了一個(gè)Attribute:JsonConverter.其底層調(diào)用如下:
[RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
[RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
public static JsonConverter? GetJsonConverter(object attributeProvider)
{
// 底層還是調(diào)用Reflection,為了性能,也緩存了對(duì)象元數(shù)據(jù)。
JsonConverterAttribute? converterAttribute = GetCachedAttribute<JsonConverterAttribute>(attributeProvider);
if (converterAttribute != null)
{
Func<object[]?, object> creator = CreatorCache.Instance.Get(converterAttribute.ConverterType);
if (creator != null)
{
return (JsonConverter)creator(converterAttribute.ConverterParameters);
}
}
return null;
}Attribute在CLR上的調(diào)用
public class NativeMethods
{
[DllImport("xxxxx", EntryPoint = "add", CallingConvention = CallingConvention.Cdecl)]
public extern static int ManagedAdd(int a, int b);
}在CLR中,同樣用來(lái)調(diào)用 C/C++ 的導(dǎo)出函數(shù)。有興趣的朋友可以使用windbg查看線程調(diào)用棧。以及在MetaData中有一張ImplMap表,存儲(chǔ)著C#方法與C++函數(shù)的mapping關(guān)系
Attribute在JIT上的調(diào)用
public class Person
{
public int id { get; set; } = 0;
[MethodImpl(MethodImplOptions.Synchronized)]
public void SyncMethod()
{
id++;
}
}JIT會(huì)自動(dòng)為該Attribute注入同步代碼


其本質(zhì)就是注入lock同步塊代碼,只是顆粒度在整個(gè)方法上。相對(duì)比較大
結(jié)論
Attrubute在C#層面,底層使用反射。因此使用自定義Attribute時(shí),酌情使用緩存來(lái)提高性能
到此這篇關(guān)于.NET Core 特性(Attribute)底層原理淺談的文章就介紹到這了,更多相關(guān).NET Core 底層原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net實(shí)現(xiàn)Gradview綁定數(shù)據(jù)庫(kù)數(shù)據(jù)并導(dǎo)出Excel的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)Gradview綁定數(shù)據(jù)庫(kù)數(shù)據(jù)并導(dǎo)出Excel的方法,涉及asp.net操作Gradview實(shí)現(xiàn)數(shù)據(jù)庫(kù)綁定及數(shù)據(jù)導(dǎo)出的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-11-11
Asp.Net Mvc2 OA 工作流設(shè)計(jì)思路[圖]
回老家上班的新公司,第一個(gè)項(xiàng)目:OA。以前沒有做過OA,因?yàn)樵O(shè)計(jì)到工作流這一塊的東西,所以自己去進(jìn)行了相關(guān)的了解,于是有了這篇博客(以下文字只是個(gè)人理解,高手漂過)2012-10-10
js獲取.aspx頁(yè)面里面的服務(wù)器控件和.ascx中的服務(wù)器控件值
用js獲取.ascx控件中服務(wù)器控件值時(shí)首先要得到服務(wù)器控件的ClientID再加上.ascx頁(yè)面里面的服務(wù)器空間ID并用"_"連接2009-02-02
ASP.NET數(shù)據(jù)庫(kù)存取圖片的方法
這篇文章主要為大家詳細(xì)介紹了ASP.NET數(shù)據(jù)庫(kù)如何存取圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
c# .net在WEB頁(yè)中的COOKIES設(shè)置技巧
c# .net在WEB頁(yè)中的COOKIES設(shè)置技巧,需要的朋友可以參考下。2011-07-07
Asp.net實(shí)現(xiàn)選擇性的保留DataTable中的列
選擇性的保留DataTable中的列(移除列/保留列不移除/移除不需要的列),很多新手朋友們都想實(shí)現(xiàn)這樣的功能,本文總結(jié)了一些可行方法,感興趣的朋友可以了解下哦2013-01-01

