千家信息网

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

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本文小编为大家详细介绍"在.NET平台怎么使用ReflectionDynamicObject优化反射",内容详细,步骤清晰,细节处理妥当,希望这篇"在.NET平台怎么使用ReflectionDynam
千家信息网最后更新 2026年11月01日在.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 : IGetter        private readonly Func _getter;        public Getter(Func getter)            _getter = getter ?? throw new ArgumentNullException(nameof(getter));            return _getter((T1)instance);    private class Setter : ISetter        private readonly Action _setter;        public Setter(Action 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();            var setter = new SortedDictionary();            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 _getters;        private readonly IReadOnlyDictionary _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 _accessors = new Dictionary();    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(_accessors);            temp[type] = new Accessor(type);            _accessors = temp;            return accessor;    #endregion}

ReflectionDynamicObject 的局限性

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

哪里用到了 ReflectionDynamicObject ?

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

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

反射 支持 主题 方法 属性 引擎 技术 平台 字段 成员 文章 优雅 代码 内容 动态 模板 笔者 类型 私有 设计 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 哈尔滨大商圈互联网科技有限公司 涨乐互联网科技 互联网科技社 互联网中国科技 壹账通互联网科技 时间互联网络科技 互联网高科技企业 天速互联网络科技有限公司 广州恒生互联网科技有限 昊天互联网科技有限公司 民营互联网公司国防科技 浙南科技城互联网大厦建设工程 高科技互联网发展前景如何 互联网金融科技名词解释 烟台灵鸽互联网科技有限公司 滨湖区互联网智能科技产品有哪些 神州科技互联网有限公司 广州梦谷互联网科技有限公司领导 珠海东科互联网科技有限公司 银川新华互联网科技学校招聘 苏州找大状互联网科技有限公司 互联网科技工作委员会毛军 齐家互联网科技 世界互联网领先科技成果 互联网金融科技平台 上海卓越科技 互联网 互联网实体化科技化 工业互联网山东科技大学 互联网营销推广黑科技 易企秀互联网科技是做什么的
0