当前位置: 代码网 > it编程>编程语言>Asp.net > .NET Core 特性(Attribute)底层原理解析

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

2024年11月25日 Asp.net 我要评论
attribute的使用场景attribute不仅仅局限于c#中,在整个.net框架中都提供了非常大的拓展点,任何地方都有attribute的影子编译器层比如 obsolete,conditional

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<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次造成的性能差距还是很明显的

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

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

结论

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

到此这篇关于.net core 特性(attribute)底层原理浅谈的文章就介绍到这了,更多相关.net core 底层原理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com