.NET Core 特性(Attribute)底层原理解析
Attribute的使用场景
Attribute不仅仅局限于C#中,在整个.NET框架中都提供了非常大的拓展点,任何地方都有Attribute的影子
- 编译器层
 比如 Obsolete,Conditional
- C#层
 GET,POST,Max,Range,Require
- CLR VM层
 StructLayout,DllImport
- JIT 层
 MethodImpl
Attribute在C#中的调用
举个常用的例子,读取枚举上的自定义特性。
    public enum Test
    {
        [EnumDescription("hhhhhh")]
        None = 0,
        [EnumDescription("xxxxxx")]
        Done =1
    }
	private static IEnumerable GetEnumDescriptions(this Enum e)
	{
		IEnumerable 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().Select(x => x.Description);
        }
		return result ?? Enumerable.Empty();
	}    可以看到,Attribute底层在C#中实现依旧是依赖反射,所以为什么说Attribute是写给代码看的注释,因此对反射的优化思路也可以用在Attribute中。
比如在代码中,使用Dictionary缓存结果集。避免过多调用反射造成的性能问题。
private static IEnumerableGetEnumDescriptionsCache(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; } } 
循环100000次造成的性能差距还是很明显的

Newtonsoft.Json对Attrubute的使用
以JsonConverter为蓝本举例说明。
    public class Person
    {
        [JsonConverter(typeof(DateTimeConverter))]
        public DateTime CreateTime { get; set; }
    }
	public class DateTimeConverter : JsonConverter
    {
        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.其底层调用如下:
        [RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
        [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
        public static JsonConverter? GetJsonConverter(object attributeProvider)
        {
			// 底层还是调用Reflection,为了性能,也缓存了对象元数据。
            JsonConverterAttribute? converterAttribute = GetCachedAttribute(attributeProvider);
            if (converterAttribute != null)
            {
                Func https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
Attribute在CLR上的调用
    public class NativeMethods
    {
        [DllImport("xxxxx", EntryPoint = "add", CallingConvention = CallingConvention.Cdecl)]
        public extern static int ManagedAdd(int a, int b);
    }在CLR中,同样用来调用 C/C++ 的导出函数。有兴趣的朋友可以使用windbg查看线程调用栈。以及在MetaData中有一张ImplMap表,存储着C#方法与C++函数的mapping关系
Attribute在JIT上的调用
    public class Person
    {
        public int id { get; set; } = 0;
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void SyncMethod()
        {
            id++;
        }
    }JIT会自动为该Attribute注入同步代码


其本质就是注入lock同步块代码,只是颗粒度在整个方法上。相对比较大
结论
Attrubute在C#层面,底层使用反射。因此使用自定义Attribute时,酌情使用缓存来提高性能
到此这篇关于.NET Core 特性(Attribute)底层原理浅谈的文章就介绍到这了,更多相关.NET Core 底层原理内容请搜索科站长以前的文章或继续浏览下面的相关文章希望大家以后多多支持科站长!
上一篇:.NET 8 强大功能 IHostedService 与 BackgroundService 实战教程
栏 目:ASP.NET
本文标题:.NET Core 特性(Attribute)底层原理解析
本文地址:https://www.fushidao.cc/wangluobiancheng/3287.html
您可能感兴趣的文章
- 09-13web前端三大主流框架
- 09-13asp.NET是前端还是后端
- 09-13asp.net还有人用吗
- 07-25ASP.NET中Onclick与OnClientClick遇到的问题
- 07-25.NET WPF 可视化树(Visual Tree)详解
- 07-25.NET MCP 文档详细指南
- 07-25.NET 中的深拷贝实现方法详解
- 07-25Asp.NET Core WebApi 配置文件详细说明
- 07-25.NET Core中获取各种路径的的方法总结
- 07-25在 .NET 中 使用 ANTLR4构建语法分析器的方法


阅读排行
推荐教程
- 07-25在 .NET 中 使用 ANTLR4构建语法分析器的方法
- 07-25ASP.NET中Onclick与OnClientClick遇到的问题
- 07-25ASP.NET Core 模型验证消息的本地化新姿势详解
- 07-25Asp.NET Core WebApi 配置文件详细说明
- 09-13asp.NET是前端还是后端
- 07-25Math.NET Numerics 开源数学库安装使用详解
- 07-25.NET Core 实现缓存的预热的方式
- 03-31详解如何在.NET代码中使用本地部署的Deepseek语言模型
- 07-25.NET根据文件的哈希值筛选重复文件的实现思路
- 07-25.NET 中的深拷贝实现方法详解




