首页 > 其他分享 >.NET Core 特性(Attribute)底层原理浅谈

.NET Core 特性(Attribute)底层原理浅谈

时间:2024-11-19 16:31:31浏览次数:1  
标签:Core return 浅谈 C# Attribute DateTime result public

简介

image
烂大街的资料不再赘述,简单来说就是给代码看的注释

Attribute的使用场景

Attribute不仅仅局限于C#中,在整个.NET框架中都提供了非常大的拓展点,任何地方都有Attribute的影子

  1. 编译器层
    比如 Obsolete,Conditional
  2. C#层
    GET,POST,Max,Range,Require
  3. CLR VM层
    StructLayout,DllImport
  4. JIT 层
    MethodImpl

Attribute在C#中的调用

举个常用的例子,读取枚举上的自定义特性。

    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#中实现依旧是依赖反射,所以为什么说Attribute是写给代码看的注释,因此对反射的优化思路也可以用在Attribute中。
比如在代码中,使用Dictionary缓存结果集。避免过多调用反射造成的性能问题。

        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;
            }
        }

循环100000次造成的性能差距还是很明显的
image

Newtonsoft.Json对Attrubute的使用

以JsonConverter为蓝本举例说明。

    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.其底层调用如下:

        [RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
        [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
        public static JsonConverter? GetJsonConverter(object attributeProvider)
        {
			// 底层还是调用Reflection,为了性能,也缓存了对象元数据。
            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上的调用

    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注入同步代码
image
image

其本质就是注入lock同步块代码,只是颗粒度在整个方法上。相对比较大

结论

Attrubute在C#层面,底层使用反射。因此使用自定义Attribute时,酌情使用缓存来提高性能

标签:Core,return,浅谈,C#,Attribute,DateTime,result,public
From: https://www.cnblogs.com/lmy5215006/p/18551715

相关文章

  • NVIDIA(Hopper)H100 Tensor Core GPU 架构
    NVIDIA(Hopper)H100TensorCoreGPU架构AI赋能个体创业致力于降低直播成本服务于商家和个人​关注他  NVIDIAH100TensorCoreGPU是NVIDIA最新的(2022年发布)通用可编程流式GPU,适用于HPC、AI、科学模拟和数据分析。H100GPU主要用于执行A......
  • 如何在Ubuntu 20.04 LTS上安装Dotnet Core?
    在本教程中,我们将向您展示如何在香港服务器的Ubuntu20.04LTS系统上安装DotnetCore。.NETCore是一个免费的开源软件框架和开源软件框架。它是由Microsoft开发的。它是由Microsoft开发的。.NETCore是一个非常强大的框架。它通常用于开发Web应用程序。步骤1.首先,通过apt在......
  • net MVC ActionResultObjectValueAttribute
    MVC返回结果IActionResultIActionResult派生类如下......
  • Asp.net Core Hosted Service(托管服务) Timer (定时任务)
    HostedService托管服务要继承IHostedService或继承BackgroundService》》》定义一个后台托管服务///<summary>///自定义后台任务类///</summary>publicclassMyHostedService:BackgroundService{///<summary>///执行任务///</summary......
  • .net core微服务 async task job示例
     Execute函数publicasyncTaskExecute(IJobExecutionContextcontext){Stopwatch_time=newStopwatch();_time.Start();stringstrRe="开始时间:"+DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");stringerrmsg=strin......
  • NetCore 3.1 大文件上传报错--413 Payload Too Large
    十年河东,十年河西,莫欺少年穷学无止境。,精益求精1、报错信息如下:RequestURL:https://xx.com/webapi/api/ad_video/UploadRequestMethod:POSTStatusCode:413PayloadTooLargeRemoteAddress:106.15.105.219:443ReferrerPolicy:strict-origin-when-cross-origin......
  • 浅谈网络文件系统原理
    本文分享自天翼云开发者社区《浅谈网络文件系统原理》,作者:谢****云什么是网络文件系统?网络文件系统(NetworkFileSystem,NFS)实现了一种软件协议,能将远端的文件系统映射到本地,使用者访问网络上的文件就像在使用自己的计算机一样。远端是专属存储系统,通常称为NAS存储。比较出名的......
  • 网络-浅谈批量通讯和自主通讯的区别
    批量通信和自动通信是两种不同的通信概念,它们在多个方面存在显著的差异。以下是对这两种通信方式的详细解释:一、批量通信定义:批量通信通常指的是在数据通信过程中,将大量的数据或信息作为一个整体或批次进行传输。特点:高效性:由于数据是以整体或批次的形式进行传输,因此可以显著......
  • 第三十三节:基于ShardingCore框架分库、分库分表实操
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......
  • TYPE-C PD浅谈(四)
    TYPE-CPD浅谈(四)当对接识别完成后,Provider会先在VBUS上提供5V,接着会在CC脚位上送出SourceCapability(SRC_CAP),格式如下:内容定义了供电的各种选项,如共有几组电源可选,相对应的电压电流等。当Consumer接收到SRC_CAP封包后,会针对电源列表的内容,挑选一组电压,再发出需求指令给Provid......