Beispiel #1
0
        private static bool VerifyMapperResultHelper(this Mapper ultraMapper,
                                                     object source, object target, ReferenceTracker referenceTracking)
        {
            //sharing the same reference or both null
            if (Object.ReferenceEquals(source, target))
            {
                return(true);
            }

            //either source or target is null
            if (source == null || target == null)
            {
                return(false);
            }

            Type sourceType = source.GetType();
            Type targetType = target.GetType();

            if (!sourceType.IsValueType && source != null)
            {
                if (referenceTracking.Contains(source, targetType))
                {
                    return(true);
                }

                if (!sourceType.IsValueType)
                {
                    referenceTracking.Add(source, targetType, target);
                }
            }

            //same value type: just compare their values
            if (sourceType == targetType && sourceType.IsBuiltIn(false))
            {
                return(source.Equals(target));
            }

            if (sourceType.IsEnumerable() && targetType.IsEnumerable())
            {
                var firstPos  = (source as IEnumerable).GetEnumerator();
                var secondPos = (target as IEnumerable).GetEnumerator();

                var hasFirst  = firstPos.MoveNext();
                var hasSecond = secondPos.MoveNext();

                while (hasFirst && hasSecond)
                {
                    if (!VerifyMapperResultHelper(ultraMapper, firstPos.Current, secondPos.Current, referenceTracking))
                    {
                        return(false);
                    }

                    hasFirst  = firstPos.MoveNext();
                    hasSecond = secondPos.MoveNext();
                }

                if (hasFirst ^ hasSecond)
                {
                    return(false);
                }
            }

            var typeMapping = ultraMapper.MappingConfiguration[
                source.GetType(), target.GetType()];

            foreach (var mapping in typeMapping.MemberMappings.Values)
            {
                if (mapping.MappingResolution == Internals.MappingResolution.RESOLVED_BY_CONVENTION &&
                    typeMapping.IgnoreMemberMappingResolvedByConvention == true)
                {
                    continue;
                }

                var sourceValue = mapping.SourceMember
                                  .ValueGetter.Compile().DynamicInvoke(source);

                var targetValue = mapping.TargetMember
                                  .ValueGetter.Compile().DynamicInvoke(target);

                var converter = mapping.CustomConverter;
                if (converter != null)
                {
                    if (mapping.MappingExpression.Parameters[0].Type == typeof(ReferenceTracker))
                    {
                        //sourceValue = converter.Compile().DynamicInvoke( referenceTracking, sourceValue, targetValue );
                    }
                    else
                    {
                        sourceValue = converter.Compile().DynamicInvoke(sourceValue);
                    }
                }

                if (!mapping.SourceMember.MemberType.IsValueType && sourceValue != null)
                {
                    if (referenceTracking.Contains(sourceValue, mapping.TargetMember.MemberType))
                    {
                        continue;
                    }

                    var result = VerifyMapperResultHelper(ultraMapper, sourceValue, targetValue, referenceTracking);
                    if (!result)
                    {
                        return(false);
                    }

                    referenceTracking.Add(sourceValue, mapping.TargetMember.MemberType, targetValue);
                }

                if (Object.ReferenceEquals(sourceValue, targetValue))
                {
                    continue;
                }

                bool isSourcePropertyNullable = Nullable.GetUnderlyingType(mapping.SourceMember.MemberType) != null;
                bool isTargetPropertyNullable = Nullable.GetUnderlyingType(mapping.TargetMember.MemberType) != null;

                if (isSourcePropertyNullable && !isTargetPropertyNullable && sourceValue == null &&
                    targetValue.Equals(mapping.TargetMember.MemberType.GetDefaultValueViaActivator()))
                {
                    continue;
                }

                if (sourceValue == null ^ targetValue == null)
                {
                    return(false);
                }

                if (sourceValue.GetType().IsEnumerable() && targetValue.GetType().IsEnumerable())
                {
                    var firstPos  = (sourceValue as IEnumerable).GetEnumerator();
                    var secondPos = (targetValue as IEnumerable).GetEnumerator();

                    var hasFirst  = firstPos.MoveNext();
                    var hasSecond = secondPos.MoveNext();

                    while (hasFirst && hasSecond)
                    {
                        if (!VerifyMapperResultHelper(ultraMapper, firstPos.Current, secondPos.Current, referenceTracking))
                        {
                            return(false);
                        }

                        hasFirst  = firstPos.MoveNext();
                        hasSecond = secondPos.MoveNext();
                    }

                    if (hasFirst ^ hasSecond)
                    {
                        return(false);
                    }
                }

                //same value type: just compare their values
                if (sourceValue.GetType() == targetValue.GetType() && sourceValue.GetType().IsValueType)
                {
                    if (!sourceValue.Equals(targetValue))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }