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)));
 }