using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; namespace VCommon.Reflection { public static class DynamicMemberAccess { private static readonly IDictionary> CachedAccessors = new ConcurrentDictionary>(); private static readonly IDictionary> CachedStaticAccessors = new ConcurrentDictionary>(); private static Func BuildInstanceAccessor(string memberName) { var pInstance = Expression.Parameter(typeof(TClass)); var access = Expression.PropertyOrField(pInstance, memberName); var expression = Expression.Lambda(access, pInstance); var del = (Func)expression.Compile(); return del; } private static Func BuildStaticAccessor(string memberName) { var member = (MemberInfo)typeof(TClass).GetProperty(memberName, BindingFlags.Static | BindingFlags.Public) ?? typeof(TClass).GetField(memberName, BindingFlags.Static | BindingFlags.Public); if (null == member) throw new ArgumentException("member not found of " + typeof(TClass).FullName, nameof(memberName)); var access = Expression.MakeMemberAccess(null, member); var expression = Expression.Lambda(access); var del = (Func)expression.Compile(); return del; } public static TPropertyType Read(TClass instance, string memberName) { if (false == CachedAccessors.TryGetValue(memberName, out var del)) { del = BuildInstanceAccessor(memberName); CachedAccessors[memberName] = del; } return del(instance); } public static TPropertyType ReadStatic(string memberName) { if (false == CachedStaticAccessors.TryGetValue(memberName, out var del)) { del = BuildStaticAccessor(memberName); CachedStaticAccessors[memberName] = del; } return del(); } } }