int IEqualityComparer <MemberInfoDelegateCacheKey> .GetHashCode(MemberInfoDelegateCacheKey obj) { unchecked { return((obj.DelegateType.GetHashCode() * 397) ^ obj.Member.GetHashCode()); } }
protected virtual Func <object, TType> GetMemberGetterInternal <TType>(MemberInfo member) { var key = new MemberInfoDelegateCacheKey(member, typeof(TType)); lock (MemberGetterCache) { Delegate value; if (!MemberGetterCache.TryGetValue(key, out value)) { GenerateGetterCode(member, typeof(TType)); ParameterExpression target = Expression.Parameter(typeof(object), "instance"); MemberExpression accessExp; if (IsStatic(member)) { accessExp = Expression.MakeMemberAccess(null, member); } else { Type declaringType = member.DeclaringType; accessExp = Expression.MakeMemberAccess(ConvertIfNeed(target, declaringType, false), member); } value = Expression .Lambda <Func <object, TType> >(ConvertIfNeed(accessExp, typeof(TType), false), target) .Compile(); MemberGetterCache[key] = value; } return((Func <object, TType>)value); } }
protected virtual Action <object, TType> GetMemberSetterInternal <TType>(MemberInfo member) { var key = new MemberInfoDelegateCacheKey(member, typeof(TType)); lock (MemberSetterCache) { Delegate action; if (!MemberSetterCache.TryGetValue(key, out action)) { var declaringType = member.DeclaringType; var fieldInfo = member as FieldInfo; #if NET_STANDARD if (declaringType.GetTypeInfo().IsValueType) #else if (declaringType.IsValueType) #endif { Action <object, TType> result; if (fieldInfo == null) { var propertyInfo = (PropertyInfo)member; result = propertyInfo.SetValue <TType>; } else { result = fieldInfo.SetValue <TType>; } MemberSetterCache[key] = result; return(result); } Expression expression; var targetParameter = Expression.Parameter(typeof(object), "instance"); var valueParameter = Expression.Parameter(typeof(TType), "value"); var target = ConvertIfNeed(targetParameter, declaringType, false); if (fieldInfo == null) { var propertyInfo = member as PropertyInfo; MethodInfo setMethod = null; if (propertyInfo != null) { setMethod = propertyInfo.GetSetMethod(true); } Should.MethodBeSupported(propertyInfo != null && setMethod != null, "supports only properties (non-readonly) and fields"); var valueExpression = ConvertIfNeed(valueParameter, propertyInfo.PropertyType, false); expression = Expression.Call(setMethod.IsStatic ? null : ConvertIfNeed(target, declaringType, false), setMethod, valueExpression); GenerateSetterCode(member, typeof(TType), propertyInfo.PropertyType); } else { expression = Expression.Field(fieldInfo.IsStatic ? null : ConvertIfNeed(target, declaringType, false), fieldInfo); expression = Expression.Assign(expression, ConvertIfNeed(valueParameter, fieldInfo.FieldType, false)); GenerateSetterCode(member, typeof(TType), fieldInfo.FieldType); } action = Expression .Lambda <Action <object, TType> >(expression, targetParameter, valueParameter) .Compile(); MemberSetterCache[key] = action; } return((Action <object, TType>)action); } }
bool IEqualityComparer <MemberInfoDelegateCacheKey> .Equals(MemberInfoDelegateCacheKey x, MemberInfoDelegateCacheKey y) { return(x.DelegateType.Equals(y.DelegateType) && (ReferenceEquals(x.Member, y.Member) || x.Member.Equals(y.Member))); }