欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET?Core?特性(Attribute)底層原理解析

 更新時間:2024年11月20日 08:53:52   作者:叫我安不理  
Attribute不僅僅局限于C#中,在整個.NET框架中都提供了非常大的拓展點(diǎn),任何地方都有Attribute的影子,這篇文章主要介紹了.NET?Core?特性(Attribute)底層原理,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下

Attribute的使用場景

Attribute不僅僅局限于C#中,在整個.NET框架中都提供了非常大的拓展點(diǎn),任何地方都有Attribute的影子

  • 編譯器層
    比如 Obsolete,Conditional
  • C#層
    GET,POST,Max,Range,Require
  • CLR VM層
    StructLayout,DllImport
  • JIT 層
    MethodImpl

Attribute在C#中的調(diào)用

舉個常用的例子,讀取枚舉上的自定義特性。

    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#中實現(xiàn)依舊是依賴反射,所以為什么說Attribute是寫給代碼看的注釋,因此對反射的優(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對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"));
        }
    }

定義了一個Attribute:JsonConverter.其底層調(diào)用如下:

        [RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
        [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
        public static JsonConverter? GetJsonConverter(object attributeProvider)
        {
			// 底層還是調(diào)用Reflection,為了性能,也緩存了對象元數(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;
        }

https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs

Attribute在CLR上的調(diào)用

    public class NativeMethods
    {
        [DllImport("xxxxx", EntryPoint = "add", CallingConvention = CallingConvention.Cdecl)]
        public extern static int ManagedAdd(int a, int b);
    }

在CLR中,同樣用來調(diào)用 C/C++ 的導(dǎo)出函數(shù)。有興趣的朋友可以使用windbg查看線程調(diào)用棧。以及在MetaData中有一張ImplMap表,存儲著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會自動為該Attribute注入同步代碼

其本質(zhì)就是注入lock同步塊代碼,只是顆粒度在整個方法上。相對比較大

結(jié)論

Attrubute在C#層面,底層使用反射。因此使用自定義Attribute時,酌情使用緩存來提高性能

到此這篇關(guān)于.NET Core 特性(Attribute)底層原理淺談的文章就介紹到這了,更多相關(guān).NET Core 底層原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論