1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| public class PropertyAccessor { private static readonly Dictionary<(Type, string), Delegate> _getterCache = new(); private static readonly Dictionary<(Type, string), Delegate> _setterCache = new();
public static Func<object, object> CreateGetter(Type type, string propertyName) { var key = (type, propertyName); if (_getterCache.TryGetValue(key, out var cached)) return (Func<object, object>)cached;
PropertyInfo prop = type.GetProperty(propertyName); if (prop == null) throw new ArgumentException($"属性 {propertyName} 不存在");
ParameterExpression instance = Expression.Parameter(typeof(object), "instance"); UnaryExpression instanceCast = Expression.Convert(instance, type); MemberExpression propertyAccess = Expression.Property(instanceCast, prop); UnaryExpression result = Expression.Convert(propertyAccess, typeof(object)); Expression<Func<object, object>> lambda = Expression.Lambda<Func<object, object>>(result, instance); Func<object, object> getter = lambda.Compile();
_getterCache[key] = getter; return getter; }
public static Action<object, object> CreateSetter(Type type, string propertyName) { var key = (type, propertyName); if (_setterCache.TryGetValue(key, out var cached)) return (Action<object, object>)cached;
PropertyInfo prop = type.GetProperty(propertyName); if (prop == null) throw new ArgumentException($"属性 {propertyName} 不存在");
ParameterExpression instance = Expression.Parameter(typeof(object), "instance"); ParameterExpression value = Expression.Parameter(typeof(object), "value"); UnaryExpression instanceCast = Expression.Convert(instance, type); UnaryExpression valueCast = Expression.Convert(value, prop.PropertyType); MethodCallExpression setProperty = Expression.Call(instanceCast, prop.SetMethod, valueCast); Expression<Action<object, object>> lambda = Expression.Lambda<Action<object, object>>(setProperty, instance, value); Action<object, object> setter = lambda.Compile();
_setterCache[key] = setter; return setter; } }
var person = new Person { Name = "Alice", Age = 30 };
var getter = PropertyAccessor.CreateGetter(typeof(Person), "Name"); object name = getter(person); Console.WriteLine(name);
var setter = PropertyAccessor.CreateSetter(typeof(Person), "Name"); setter(person, "Bob"); Console.WriteLine(person.Name);
|