123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq.Expressions;
- using System.Reflection;
- namespace VCommon.Reflection
- {
- public static class DynamicMemberAccess<TClass, TPropertyType>
- {
- private static readonly IDictionary<string, Func<TClass, TPropertyType>> CachedAccessors = new ConcurrentDictionary<string, Func<TClass, TPropertyType>>();
- private static readonly IDictionary<string, Func<TPropertyType>> CachedStaticAccessors = new ConcurrentDictionary<string, Func<TPropertyType>>();
- private static Func<TClass, TPropertyType> BuildInstanceAccessor(string memberName)
- {
- var pInstance = Expression.Parameter(typeof(TClass));
- var access = Expression.PropertyOrField(pInstance, memberName);
- var expression = Expression.Lambda(access, pInstance);
- var del = (Func<TClass, TPropertyType>)expression.Compile();
- return del;
- }
- private static Func<TPropertyType> 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<TPropertyType>)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();
- }
- }
- }
|