我的编程空间,编程开发者的网络收藏夹
学习永远不晚

在.NET平台怎么使用ReflectionDynamicObject优化反射

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

在.NET平台怎么使用ReflectionDynamicObject优化反射

本文小编为大家详细介绍“在.NET平台怎么使用ReflectionDynamicObject优化反射”,内容详细,步骤清晰,细节处理妥当,希望这篇“在.NET平台怎么使用ReflectionDynamicObject优化反射”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

基于封装的原则,API 的设计者会将部分成员(属性、字段、方法等)隐藏以保证健壮性。但总有需要直接访问这些私有成员的情况。

为了访问一个类型的私有成员,除了更改 API 设计还有就是使用反射技术:

public class MyApi{public MyApi(){_createdAt = DateTime.Now;}private DateTime _createdAt;public int ShowTimes { get; private set; }public void ShowCreateTime(){Console.WriteLine(_createdAt);ShowTimes++;}}void Main(){var api = new MyApi();var field = api.GetType().GetField("_createdAt", BindingFlags.NonPublic | BindingFlags.Instance);var value = field.GetValue(api);Console.WriteLine(value);}

这种写法并不优雅:

代码冗长,编写麻烦。实现比较绕,不太直观。

笔者基于“动态类型技术”探索出了一种相对来说比较优雅的方案用于美化上述代码,并为其命名为 ReflectionDynamicObject :

void Main(){    var api = new MyApi();    dynamic wrapper = ReflectionDynamicObject.Wrap(api);    Console.WriteLine(wrapper._createdAt);}

除了支持获取值,ReflectionDynamicObject 还支持赋值:

void Main(){    var api = new MyApi();    dynamic wrapper = ReflectionDynamicObject.Wrap(api);    wrapper._createdAt = new DateTime(2022, 2, 2, 22, 22, 22);    api.ShowCreateTime();}

除了字段,当然也支持对属性的操作:

void Main(){    var api = new MyApi();    dynamic wrapper = ReflectionDynamicObject.Wrap(api);    wrapper.ShowTimes = 100;    Console.WriteLine(wraper.ShowTimes);}

在对属性的支持上,ReflectionDynamicObject 使用了“快速反射”技术,将取值和复制操作生成了委托以优化性能。

ReflectionDynamicObject 的实现原理

ReflectionDynamicObject 派生自 DynamicObject ,其内部通过反射技术获取到所有的属性和字段并对其 getter 和 setter 方法进行存储并通过 TryGetMember 和 TrySetMember 方法经运行时调用。

ReflectionDynamicObject 的源代码

public sealed class ReflectionDynamicObject : DynamicObject{    private readonly object _instance;    private readonly Accessor _accessor;    private ReflectionDynamicObject(object instance)    {        _instance = instance ?? throw new ArgumentNullException(nameof(instance));        _accessor = GetAccessor(instance.GetType());    }    public static ReflectionDynamicObject Wrap(Object value)        if (value == null) throw new ArgumentNullException(nameof(value));        return new ReflectionDynamicObject(value);    public override bool TryGetMember(GetMemberBinder binder, out object result)        if (_accessor.TryFindGetter(binder.Name, out var getter))        {            result = getter.Get(_instance);            return true;        }        return base.TryGetMember(binder, out result);    public override bool TrySetMember(SetMemberBinder binder, object value)        if (_accessor.TryFindSetter(binder.Name, out var setter))            setter.Set(_instance, value);        return base.TrySetMember(binder, value);    #region 快速反射    private interface IGetter        object Get(object instance);    private interface ISetter        void Set(object instance, object value);    private class Getter : IGetter        private FieldInfo _field;        public Getter(FieldInfo field)            _field = field ?? throw new ArgumentNullException(nameof(field));        public object Get(object instance)            return _field.GetValue(instance);    private class Setter : ISetter        public Setter(FieldInfo field)        public void Set(object instance, object value)            _field.SetValue(instance, value);    private class Getter<T1, T2> : IGetter        private readonly Func<T1, T2> _getter;        public Getter(Func<T1, T2> getter)            _getter = getter ?? throw new ArgumentNullException(nameof(getter));            return _getter((T1)instance);    private class Setter<T1, T2> : ISetter        private readonly Action<T1, T2> _setter;        public Setter(Action<T1, T2> setter)            this._setter = setter ?? throw new ArgumentNullException(nameof(setter));            this._setter.Invoke((T1)instance, (T2)value);    private class Accessor        public Accessor(Type type)            this._type = type ?? throw new ArgumentNullException(nameof(_type));            var getter = new SortedDictionary<string, IGetter>();            var setter = new SortedDictionary<string, ISetter>();            var fields = _type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            foreach (var field in fields)            {                getter[field.Name] = new Getter(field);                setter[field.Name] = new Setter(field);            }            var props = _type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);            foreach (var item in props)                if (item.CanRead)                {                    var method = item.GetMethod;                    var funcType = typeof(Func<,>).MakeGenericType(item.DeclaringType, item.PropertyType);                    var func = method.CreateDelegate(funcType);                    var getterType = typeof(Getter<,>).MakeGenericType(item.DeclaringType, item.PropertyType);                    var get = (IGetter)Activator.CreateInstance(getterType, func);                    getter[item.Name] = get;                }                if (item.CanWrite)                    var method = item.SetMethod;                    var actType = typeof(Action<,>).MakeGenericType(item.DeclaringType, item.PropertyType);                    var act = method.CreateDelegate(actType);                    var setterType = typeof(Setter<,>).MakeGenericType(item.DeclaringType, item.PropertyType);                    var set = (ISetter)Activator.CreateInstance(setterType, act);                    setter[item.Name] = set;            _getters = getter;            _setters = setter;        private readonly Type _type;        private readonly IReadOnlyDictionary<string, IGetter> _getters;        private readonly IReadOnlyDictionary<string, ISetter> _setters;        public bool TryFindGetter(string name, out IGetter getter) => _getters.TryGetValue(name, out getter);        public bool TryFindSetter(string name, out ISetter setter) => _setters.TryGetValue(name, out setter);    private static Dictionary<Type, Accessor> _accessors = new Dictionary<Type, Accessor>();    private static object _accessorsLock = new object();    private static Accessor GetAccessor(Type type)        if (_accessors.TryGetValue(type, out var accessor)) return accessor;        lock (_accessorsLock)            if (_accessors.TryGetValue(type, out accessor)) return accessor;            accessor = new Accessor(type);            var temp = new Dictionary<Type, Accessor>(_accessors);            temp[type] = new Accessor(type);            _accessors = temp;            return accessor;    #endregion}

ReflectionDynamicObject 的局限性

基于复杂度的考虑,ReflectionDynamicObject 并未添加对“方法”的支持。这也就意味着对方法的调用是缺失的。虽然动态行为让程序摆脱了对字符串的依赖,但是该实现对“重构”的支持仍然不友好。

哪里用到了 ReflectionDynamicObject ?

Liquid 主题引擎 是笔者根据 Liquid 语言和 Shopify 主题机制并采用 Fluid 模板引擎实现的一套 HTML 主题引擎。该引擎允许最终用户自由的修改自己的主题模板而不会对宿主造成影响。最终目标是做到多语言、多主题、高扩展性以及所见即所得。

读到这里,这篇“在.NET平台怎么使用ReflectionDynamicObject优化反射”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

在.NET平台怎么使用ReflectionDynamicObject优化反射

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

在.NET平台怎么使用ReflectionDynamicObject优化反射

本文小编为大家详细介绍“在.NET平台怎么使用ReflectionDynamicObject优化反射”,内容详细,步骤清晰,细节处理妥当,希望这篇“在.NET平台怎么使用ReflectionDynamicObject优化反射”文章能帮助大家
2023-06-29

怎么在java中利用反射实例化对象

怎么在java中利用反射实例化对象?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系
2023-06-14

怎么在java中使用反射调用方法

这篇文章将为大家详细讲解有关怎么在java中使用反射调用方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发
2023-06-14

怎么在python中使用序列化与反序列化

这篇文章将为大家详细讲解有关怎么在python中使用序列化与反序列化,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。python有哪些常用库python常用的库:1.requesuts;2.s
2023-06-14

怎么在css中使用willchange优化性能

本篇文章为大家展示了怎么在css中使用willchange优化性能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。css的三种引入方式1.行内样式,最直接最简单的一种,直接对HTML标签使用style
2023-06-08

怎么使用docker创建和运行跨平台的容器化mssql数据库

今天小编给大家分享一下怎么使用docker创建和运行跨平台的容器化mssql数据库的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下
2023-06-30

怎么在MySQL中使用sum、case和when优化统计查询

怎么在MySQL中使用sum、case和when优化统计查询?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。表结构如下:CREATE TABLE `statist
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录