private void UpdateChildMemberDataSources(ObjectMapperData toTargetMapperData)
        {
            var targetMemberDataSources = MapperData.DataSourcesByTargetMember;
            var targetMembers           = targetMemberDataSources.Keys.ToArray();
            var dataSources             = targetMemberDataSources.Values.ToArray();

            var toTargetTargetMemberDataSources = toTargetMapperData.DataSourcesByTargetMember;

            var targetMembersCount = targetMembers.Length;
            var targetMemberIndex  = 0;

            foreach (var toTargetMemberAndDataSource in toTargetTargetMemberDataSources)
            {
                var toTargetMember = toTargetMemberAndDataSource.Key.LeafMember;

                for (var i = targetMemberIndex; i < targetMembersCount; ++i)
                {
                    ++targetMemberIndex;

                    var targetMember = targetMembers[i];

                    if (!targetMember.LeafMember.Equals(toTargetMember))
                    {
                        continue;
                    }

                    if (!dataSources[i].HasValue)
                    {
                        targetMemberDataSources[targetMember] = toTargetMemberAndDataSource.Value;
                    }

                    break;
                }
            }
        }
예제 #2
0
        private Expression GetMappingBlock(IList <Expression> mappingExpressions, ObjectMapperData mapperData)
        {
            if (mappingExpressions[0].NodeType != ExpressionType.Block)
            {
                var objectAssignment = mappingExpressions.First(exp => exp.NodeType == ExpressionType.Assign);

                if (mappingExpressions.Last() == objectAssignment)
                {
                    var assignment    = (BinaryExpression)objectAssignment;
                    var assignedValue = assignment.Right;

                    if (assignedValue.NodeType == ExpressionType.Invoke)
                    {
                        assignedValue = assignedValue.Replace(mapperData.InstanceVariable, mapperData.TargetObject);
                    }

                    if (mappingExpressions.Count == 1)
                    {
                        return(Expression.Block(assignedValue));
                    }

                    mappingExpressions[mappingExpressions.Count - 1] = assignedValue;

                    return(Expression.Block(mappingExpressions));
                }
            }

            mappingExpressions.Add(Expression.Label(mapperData.ReturnLabelTarget, GetReturnValue(mapperData)));

            var mappingBlock = Expression.Block(new[] { mapperData.InstanceVariable }, mappingExpressions);

            return(mappingBlock);
        }
예제 #3
0
        private static Expression GetChildMapping(
            IObjectMappingData childMappingData,
            MappingValues mappingValues,
            int dataSourceIndex,
            ObjectMapperData declaredTypeMapperData)
        {
            var childMapperData = childMappingData.MapperData;

            if (childMapperData.TargetMemberEverRecurses())
            {
                var mapRecursionCall = GetMapRecursionCallFor(
                    childMappingData,
                    mappingValues.SourceValue,
                    dataSourceIndex,
                    declaredTypeMapperData);

                return(mapRecursionCall);
            }

            var inlineMappingBlock = GetInlineMappingBlock(
                childMappingData,
                MappingDataFactory.ForChildMethod,
                mappingValues,
                new[]
            {
                mappingValues.SourceValue,
                mappingValues.TargetValue,
                mappingValues.EnumerableIndex,
                Expression.Constant(childMapperData.TargetMember.RegistrationName),
                Expression.Constant(dataSourceIndex),
                declaredTypeMapperData.GetParentMappingDataObjectAccess()
            });

            return(inlineMappingBlock);
        }
예제 #4
0
        private static IEnumerable <DictionaryTargetMember> EnumerateTargetMembers(
            IEnumerable <Member> sourceMembers,
            DictionaryTargetMember targetDictionaryMember,
            ObjectMapperData mapperData,
            Func <Member, string> targetMemberNameFactory)
        {
            foreach (var sourceMember in sourceMembers)
            {
                var targetEntryMemberName = targetMemberNameFactory.Invoke(sourceMember);
                var targetEntryMember     = targetDictionaryMember.Append(sourceMember.DeclaringType, targetEntryMemberName);

                if (targetDictionaryMember.HasObjectEntries)
                {
                    targetEntryMember = (DictionaryTargetMember)targetEntryMember.WithType(sourceMember.Type);
                }

                var entryMapperData = new ChildMemberMapperData(targetEntryMember, mapperData);
                var configuredKey   = GetCustomKeyOrNull(entryMapperData);

                if (configuredKey != null)
                {
                    targetEntryMember.SetCustomKey(configuredKey);
                }

                if (!sourceMember.IsSimple && !targetDictionaryMember.HasComplexEntries)
                {
                    targetEntryMember = targetEntryMember.WithTypeOf(sourceMember);
                }

                yield return(targetEntryMember);
            }
        }
예제 #5
0
        public static Expression GetChildMapping(
            IObjectMappingData childMappingData,
            MappingValues mappingValues,
            int dataSourceIndex,
            ObjectMapperData declaredTypeMapperData)
        {
            var childMapperData = childMappingData.MapperData;

            if (childMapperData.IsRepeatMapping &&
                childMapperData.RuleSet.RepeatMappingStrategy.AppliesTo(childMapperData))
            {
                var repeatMappingCall = childMapperData
                                        .RuleSet
                                        .RepeatMappingStrategy
                                        .GetMapRepeatedCallFor(
                    childMappingData,
                    mappingValues,
                    dataSourceIndex,
                    declaredTypeMapperData);

                return(repeatMappingCall);
            }

            var inlineMappingBlock = GetInlineMappingBlock(
                childMappingData,
                mappingValues,
                MappingDataCreationFactory.ForChild(mappingValues, dataSourceIndex, childMapperData));

            return(inlineMappingBlock);
        }
예제 #6
0
        public static Expression UseLocalSourceValueVariableIfAppropriate(
            Expression mappingExpression,
            ObjectMapperData mapperData)
        {
            if (mapperData.Context.IsForDerivedType ||
                !mapperData.Context.IsStandalone ||
                mapperData.UseSingleMappingExpression())
            {
                return(mappingExpression);
            }

            if (!ShouldUseLocalSourceValueVariable(mapperData.SourceObject, mappingExpression, mapperData))
            {
                return(mappingExpression);
            }

            var sourceValueVariableName = GetSourceValueVariableName(mapperData);
            var sourceValueVariable     = Expression.Variable(mapperData.SourceType, sourceValueVariableName);

            return(UseLocalValueVariable(
                       sourceValueVariable,
                       mapperData.SourceObject,
                       mappingExpression,
                       performValueReplacement: true));
        }
예제 #7
0
        private ParameterExpression GetMappingDataObject(ObjectMapperData parent)
        {
            var mdType = typeof(IObjectMappingData <,>).MakeGenericType(SourceType, TargetType);

            var variableNameIndex = default(int?);

            while (parent != null)
            {
                if (parent.MappingDataObject.Type == mdType)
                {
                    variableNameIndex = variableNameIndex.HasValue ? (variableNameIndex + 1) : 2;
                }

                parent = parent.Parent;
            }

            var mappingDataVariableName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}To{1}Data{2}",
                SourceType.GetShortVariableName(),
                TargetType.GetShortVariableName().ToPascalCase(),
                variableNameIndex);

            var parameter = Expression.Parameter(mdType, mappingDataVariableName);

            return(parameter);
        }
예제 #8
0
        private static IEnumerable <DictionaryTargetMember> GetParentContextFlattenedTargetMembers(
            ObjectMapperData mapperData,
            DictionaryTargetMember targetDictionaryMember)
        {
            while (mapperData.Parent != null)
            {
                mapperData = mapperData.Parent;

                var sourceMembers = GlobalContext.Instance
                                    .MemberCache
                                    .GetSourceMembers(mapperData.SourceType)
                                    .SelectMany(sm => MatchingFlattenedMembers(sm, targetDictionaryMember))
                                    .ToArray();

                var targetMembers = EnumerateTargetMembers(
                    sourceMembers,
                    targetDictionaryMember,
                    mapperData,
                    m => m.Name.StartsWithIgnoreCase(targetDictionaryMember.Name)
                       ? m.Name.Substring(targetDictionaryMember.Name.Length)
                       : m.Name);

                foreach (var targetMember in targetMembers)
                {
                    yield return(targetMember);
                }
            }
        }
예제 #9
0
        public static Expression ForChild(
            MappingValues mappingValues,
            int dataSourceIndex,
            ObjectMapperData childMapperData)
        {
            if (UseAsConversion(childMapperData, out var asConversion))
            {
                return(asConversion);
            }

            var createMethod = MappingDataFactory
                               .ForChildMethod
                               .MakeGenericMethod(childMapperData.SourceType, childMapperData.TargetType);

            var createCall = Expression.Call(
                createMethod,
                mappingValues.SourceValue,
                mappingValues.TargetValue,
                mappingValues.EnumerableIndex,
                childMapperData.TargetMember.RegistrationName.ToConstantExpression(),
                dataSourceIndex.ToConstantExpression(),
                childMapperData.Parent.MappingDataObject);

            return(createCall);
        }
예제 #10
0
        private static IEnumerable <QualifiedMember> EnumerateAllTargetMembers(ObjectMapperData mapperData)
        {
            var sourceMembers          = GlobalContext.Instance.MemberCache.GetSourceMembers(mapperData.SourceType);
            var targetDictionaryMember = (DictionaryTargetMember)mapperData.TargetMember;

            var targetMembers = EnumerateTargetMembers(
                sourceMembers,
                targetDictionaryMember,
                mapperData,
                m => m.Name);

            foreach (var targetMember in targetMembers)
            {
                yield return(targetMember);
            }

            if (mapperData.IsRoot)
            {
                yield break;
            }

            foreach (var targetMember in GetParentContextFlattenedTargetMembers(mapperData, targetDictionaryMember))
            {
                yield return(targetMember);
            }
        }
        public static Expression ForElement(
            MappingValues mappingValues,
            ObjectMapperData elementMapperData)
        {
            if (UseAsConversion(elementMapperData, out var asConversion))
            {
                return(asConversion);
            }

            var createMethod = MappingDataFactory
                               .ForElementMethod
                               .MakeGenericMethod(mappingValues.SourceValue.Type, mappingValues.TargetValue.Type);

            var enumerableMappingDataObject = elementMapperData.Context.IsStandalone
                ? typeof(IObjectMappingData).ToDefaultExpression()
                : (Expression)elementMapperData.Parent.MappingDataObject;

            var createCall = Expression.Call(
                createMethod,
                mappingValues.SourceValue,
                mappingValues.TargetValue,
                mappingValues.ElementIndex,
                mappingValues.ElementKey.GetConversionToObject(),
                enumerableMappingDataObject);

            return(createCall);
        }
예제 #12
0
        private static bool UseExistingMapperData <TSource, TTarget>(
            ObjectMappingData <TSource, TTarget> mappingData,
            out ObjectMapperData existingMapperData)
        {
            if (!mappingData.IsPartOfRepeatedMapping)
            {
                existingMapperData = null;
                return(false);
            }

            // RepeatedMappings are invoked through the entry point MapperData, which assigns
            // itself as the ObjectMappingData's parent. If a repeated mapping then needs to
            // do a runtime-typed child mapping, we're able to reuse the parent MapperData
            // by finding it from the entry point:
            var parentMapperData = mappingData.Parent.MapperData;
            var membersSource    = mappingData.MapperKey.GetMembersSource(parentMapperData);

            if (!(membersSource is IChildMembersSource childMembersSource))
            {
                existingMapperData = null;
                return(false);
            }

            var mapperTypes = new[] { typeof(TSource), typeof(TTarget) };

            existingMapperData = GetMapperDataOrNull(
                parentMapperData,
                mapperTypes,
                childMembersSource.TargetMemberRegistrationName);

            return(existingMapperData != null);
        }
예제 #13
0
        public ObjectMapper(
            Expression <MapperFunc <TSource, TTarget> > mappingLambda,
            ObjectMapperData mapperData)
        {
            MappingLambda = mappingLambda;
            MapperData    = mapperData;

            if (mapperData.Context.Compile)
            {
                _mapperFunc = mappingLambda.Compile();
            }

            if (mapperData.Context.NeedsChildMapping)
            {
                _childMappersByKey = mapperData.MapperContext.Cache.CreateNew <ObjectMapperKeyBase, IObjectMapper>();
            }
            else if (mapperData.Context.NeedsElementMapping)
            {
                _elementMappersByKey = mapperData.MapperContext.Cache.CreateNew <ObjectMapperKeyBase, IObjectMapper>();
            }

            if (mapperData.HasMapperFuncs)
            {
                _recursionMappingFuncsByKey = CreateRecursionMapperFuncs();
            }
        }
예제 #14
0
 public static bool UseLocalSourceValueVariable(
     Expression sourceValue,
     Expression mapping,
     ObjectMapperData mapperData)
 {
     return((sourceValue.NodeType != ExpressionType.Parameter) &&
            SourceAccessFinder.MultipleAccessesExist(mapperData, mapping));
 }
예제 #15
0
 public MapperDataContext(
     ObjectMapperData mapperData,
     bool isStandalone,
     bool isForDerivedType)
 {
     _mapperData      = mapperData;
     IsStandalone     = isStandalone;
     IsForDerivedType = isForDerivedType;
 }
예제 #16
0
 private MapperDataContext(
     ObjectMapperData mapperData,
     bool isStandalone,
     bool isForDerivedType,
     IBasicMapperData basicMapperData)
 {
     _mapperData      = mapperData;
     IsStandalone     = isStandalone;
     IsForDerivedType = isForDerivedType;
     UseLocalVariable = isForDerivedType || ShouldUseLocalVariable(basicMapperData);
 }
예제 #17
0
        private static QualifiedMember GetTargetMember(
            string targetMemberRegistrationName,
            ObjectMapperData mapperData)
        {
            var targetMember = mapperData
                               .DataSourcesByTargetMember
                               .Keys
                               .FirstOrDefault(k => k.RegistrationName == targetMemberRegistrationName);

            return(targetMember);
        }
예제 #18
0
 private MapperDataContext(
     ObjectMapperData mapperData,
     bool isStandalone,
     bool isForDerivedType,
     IQualifiedMemberContext context)
 {
     _mapperData      = mapperData;
     IsStandalone     = isStandalone;
     IsForDerivedType = isForDerivedType;
     UseLocalVariable = isForDerivedType || ShouldUseLocalVariable(context);
 }
        private static void UpdateEnumerableVariablesIfAppropriate(
            ObjectMapperData fromMapperData,
            ObjectMapperData toMapperData)
        {
            if (fromMapperData.EnumerablePopulationBuilder.TargetVariable == null)
            {
                return;
            }

            toMapperData.LocalVariable = fromMapperData.LocalVariable;
            toMapperData.EnumerablePopulationBuilder.TargetVariable = fromMapperData.EnumerablePopulationBuilder.TargetVariable;
        }
예제 #20
0
        private static bool UseAsConversion(ObjectMapperData childMapperData, out Expression conversion)
        {
            if (childMapperData.Context.IsStandalone)
            {
                conversion = childMapperData
                             .DeclaredTypeMapperData
                             .GetAsCall(childMapperData.SourceType, childMapperData.TargetType);

                return(true);
            }

            conversion = null;
            return(false);
        }
예제 #21
0
        public EnumerablePopulationBuilder(ObjectMapperData omd)
        {
            _omd = omd;
            _sourceItemsSelector = new SourceItemsSelector(this);

            _sourceElementType     = omd.SourceType.GetEnumerableElementType();
            _targetTypeHelper      = new EnumerableTypeHelper(omd.TargetType, omd.TargetMember.ElementType);
            _targetElementType     = _targetTypeHelper.ElementType;
            ElementTypesAreTheSame = _sourceElementType == _targetElementType;
            ElementTypesAreSimple  = _targetElementType.IsSimple();

            _sourceElementParameter = _sourceElementType.GetOrCreateParameter();

            _populationExpressions = new List <Expression>();
        }
예제 #22
0
        private static Expression GetCreateMappingDataCall(
            MethodInfo createMethod,
            ObjectMapperData childMapperData,
            Expression[] createMethodCallArguments)
        {
            if (childMapperData.Context.IsStandalone)
            {
                return(childMapperData.DeclaredTypeMapperData
                       .GetAsCall(childMapperData.SourceType, childMapperData.TargetType));
            }

            return(Expression.Call(
                       createMethod.MakeGenericMethod(childMapperData.SourceType, childMapperData.TargetType),
                       createMethodCallArguments));
        }
 private SimpleMemberMapperData(
     IQualifiedMember sourceMember,
     QualifiedMember targetMember,
     ObjectMapperData enumerableMapperData)
     : base(
         enumerableMapperData.RuleSet,
         sourceMember,
         targetMember,
         enumerableMapperData,
         enumerableMapperData.MapperContext)
 {
     ParentObject      = GetParentObjectAccess();
     ElementIndex      = GetElementIndexAccess();
     ElementKey        = GetElementKeyAccess();
     ElementIndexValue = enumerableMapperData.EnumerablePopulationBuilder.Counter.GetConversionTo <int?>();
 }
예제 #24
0
        public static Expression UseLocalToTargetDataSourceVariableIfAppropriate(
            ObjectMapperData mapperData,
            ObjectMapperData toTargetMapperData,
            Expression toTargetDataSourceValue,
            Expression mappingExpression)
        {
            if (!toTargetMapperData.Context.UsesMappingDataObject)
            {
                return(mappingExpression);
            }

            return(UseLocalValueVariable(
                       toTargetMapperData.MappingDataObject,
                       MappingDataCreationFactory.ForToTarget(mapperData, toTargetDataSourceValue),
                       mappingExpression));
        }
예제 #25
0
        public static Expression ForToTarget(
            ObjectMapperData parentMapperData,
            Expression toTargetDataSource)
        {
            var withSourceMethod = parentMapperData
                                   .MappingDataObject
                                   .Type
                                   .GetPublicInstanceMethod("WithSource")
                                   .MakeGenericMethod(toTargetDataSource.Type);

            var withSourceCall = Expression.Call(
                parentMapperData.MappingDataObject,
                withSourceMethod,
                toTargetDataSource);

            return(withSourceCall);
        }
예제 #26
0
        private static IDataSource GetMappingFactoryDataSource(
            ObjectMapperData mapperData,
            ConfiguredObjectFactory factory)
        {
            var condition             = factory.GetConditionOrNull(mapperData);
            var value                 = factory.Create(mapperData);
            var returnLabelMapperData = mapperData.OriginalMapperData ?? mapperData;
            var returnValue           = returnLabelMapperData.GetReturnExpression(value);

            return(new ConfiguredDataSource(
                       mapperData.SourceMember,
                       condition,
                       returnValue,
                       factory.ConfigInfo.IsSequentialConfiguration,
                       factory.ConfigInfo.HasTargetMemberMatcher(),
                       mapperData));
        }
예제 #27
0
        private static Expression GetMapRecursionCallFor(
            IObjectMappingData childMappingData,
            Expression sourceValue,
            int dataSourceIndex,
            ObjectMapperData declaredTypeMapperData)
        {
            var childMapperData = childMappingData.MapperData;

            childMapperData.RegisterRequiredMapperFunc(childMappingData);

            var mapRecursionCall = declaredTypeMapperData.GetMapRecursionCall(
                sourceValue,
                childMapperData.TargetMember,
                dataSourceIndex);

            return(mapRecursionCall);
        }
예제 #28
0
        private static bool CreateElementMappingDataFor(
            ObjectMapperData mapperData,
            Expression sourceElementValue)
        {
            if (!mapperData.TargetMemberIsEnumerableElement())
            {
                return(true);
            }

            if (mapperData.TargetMember.IsEnumerable)
            {
                return(!mapperData.EnumerablePopulationBuilder.TargetElementsAreSimple &&
                       sourceElementValue.Type.IsAssignableTo(mapperData.SourceMember.ElementType));
            }

            return(false);
        }
        private static Expression GetObjectRegistrationCallOrNull(ObjectMapperData mapperData)
        {
            if (mapperData.TargetTypeWillNotBeMappedAgain)
            {
                return(null);
            }

            if (mapperData.MapperContext.UserConfigurations.DisableObjectTracking(mapperData))
            {
                return(null);
            }

            return(Expression.Call(
                       mapperData.EntryPointMapperData.MappingDataObject,
                       _registerMethod.MakeGenericMethod(mapperData.SourceType, mapperData.TargetType),
                       mapperData.SourceObject,
                       mapperData.InstanceVariable));
        }
예제 #30
0
        private bool IsTargetTypeFirstMapping(ObjectMapperData parent)
        {
            if (IsRoot)
            {
                return(true);
            }

            while (parent != null)
            {
                if (parent.HasTypeBeenMapped(TargetType, this))
                {
                    return(false);
                }

                parent = parent.Parent;
            }

            return(true);
        }