千家信息网

在.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安全错误 数据库的锁怎样保障安全 广州淘业互联网络科技 金融科技还是互联网 互联网 卓越科技 科技创新互联网企业 科技互联网创业计划书 互联网科技汛 天扬科技互联网广告 居家互联网科技有限公司 科技伦理 互联网公司 成都玖崟互联网科技有限公司乐商圈怎么样 互联网企业和科技型企业 广州恒生互联网科技有限 岳阳华臻互联网科技有限公司 互联网科技研发水平 互联网保险科技创业 互联网数据科技专业 皮皮虾互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司 互联网科技机房 数字互联网科技有限公司 科技互联网技术 互联网科技有限公司 翻译 青岛中康互联网医疗科技有限公司 世界互联网科技公司市值排名 千方科技属于互联网企业吗 燊美集互联网科技有限公司 华夏恒生互联网科技013171 信承诺互联网科技有限公司 吉林省码上互联网科技电话 河南商务圈互联网科技有限公司
0