public MappingCreationContext WithToTargetDataSource(IDataSource dataSource)
        {
            var newSourceMappingData = MappingData.WithToTargetSource(dataSource.SourceMember);
            var isAlternate          = !dataSource.IsSequential;

            var newContext = new MappingCreationContext(newSourceMappingData)
            {
                InstantiateLocalVariable = isAlternate
            };

            var newMapperData = newContext.MapperData;

            newMapperData.SourceObject = dataSource.Value;
            newMapperData.TargetObject = MapperData.TargetObject;

            if (TargetMember.IsComplex)
            {
                if (isAlternate)
                {
                    newMapperData.LocalVariable = MapperData.LocalVariable;
                }

                newMapperData.TargetInstance = MapperData.TargetInstance;
            }
            else if (TargetMember.IsEnumerable)
            {
                UpdateEnumerableVariablesIfAppropriate(MapperData, newMapperData);
            }

            return(newContext);
        }
示例#2
0
            public MappingCreationContext WithDataSource(IDataSource newDataSource)
            {
                var newSourceMappingData = MappingData.WithSource(newDataSource.SourceMember);

                newSourceMappingData.MapperKey = new RootObjectMapperKey(
                    RuleSet,
                    newSourceMappingData.MappingTypes,
                    new FixedMembersMembersSource(newDataSource.SourceMember, TargetMember));

                var newContext = new MappingCreationContext(newSourceMappingData, mappingExpressions: MappingExpressions)
                {
                    InstantiateLocalVariable = false
                };

                newContext.MapperData.SourceObject = newDataSource.Value;
                newContext.MapperData.TargetObject = MapperData.TargetObject;

                if (TargetMember.IsComplex)
                {
                    newContext.MapperData.TargetInstance = MapperData.TargetInstance;
                }
                else if (_mapperDataHasRootEnumerableVariables)
                {
                    UpdateEnumerableVariables(MapperData, newContext.MapperData);
                }

                return(newContext);
            }
 private void InsertShortCircuitReturns(MappingCreationContext context)
 {
     if (ShortCircuitFactories != Enumerable <ShortCircuitFactory> .EmptyArray)
     {
         context.MappingExpressions.InsertRange(0, EnumerateShortCircuitReturns(context));
     }
 }
        private IEnumerable <Expression> GetConfiguredToTargetDataSourceMappings(
            MappingCreationContext context)
        {
            if (context.MapperData.Context.IsForToTargetMapping)
            {
                yield break;
            }

            var toTargetDataSources = context
                                      .ToTargetDataSources
                                      .Filter(cds => cds.IsSequential);

            var i = 0;

            foreach (var toTargetDataSource in toTargetDataSources)
            {
                var toTargetMapping = GetConfiguredToTargetDataSourceMappingOrNull(
                    context,
                    toTargetDataSource,
                    isFirstDataSource: i == 0);

                ++i;

                if (toTargetMapping != null)
                {
                    yield return(toTargetMapping);
                }
            }
        }
示例#5
0
        protected override void AddObjectPopulation(MappingCreationContext context)
        {
            Expression population;

            if (!context.MapperData.TargetMember.IsDictionary)
            {
                population = GetDictionaryPopulation(context.MappingData);
                goto ReturnPopulation;
            }

            var assignmentFactory = GetDictionaryAssignmentFactoryOrNull(context, out var useAssignmentOnly);

            if (useAssignmentOnly)
            {
                context.MappingExpressions.Add(assignmentFactory.Invoke(context.MappingData));
                return;
            }

            population = GetDictionaryPopulation(context.MappingData);
            var assignment = assignmentFactory?.Invoke(context.MappingData);

            if (assignment != null)
            {
                context.MappingExpressions.Add(assignment);
            }

ReturnPopulation:
            context.MappingExpressions.AddUnlessNullOrEmpty(population);
        }
示例#6
0
 private void AddPopulationsAndCallbacks(MappingCreationContext context)
 {
     context.MappingExpressions.AddUnlessNullOrEmpty(context.PreMappingCallback);
     context.MappingExpressions.AddRange(GetObjectPopulation(context));
     context.MappingExpressions.AddRange(GetConfiguredToTargetDataSourceMappings(context));
     context.MappingExpressions.AddUnlessNullOrEmpty(context.PostMappingCallback);
 }
        private void AddPopulationsAndCallbacks(MappingCreationContext context)
        {
            AddPopulationsAndCallbacks(this, context, (factory, ctx) =>
            {
                var mappingExpressions     = ctx.MappingExpressions;
                var mappingExpressionCount = mappingExpressions.Count;

                factory.AddObjectPopulation(ctx);
                mappingExpressions.AddRange(GetConfiguredToTargetDataSourceMappings(ctx));

                if (!context.RemoveEmptyMappings)
                {
                    return;
                }

                var addedExpressionCount = mappingExpressions.Count - mappingExpressionCount;

                if (addedExpressionCount == 0)
                {
                    return;
                }

                if (mappingExpressionCount > 0)
                {
                    mappingExpressions = mappingExpressions
                                         .GetRange(mappingExpressionCount, addedExpressionCount);
                }

                if (NothingIsBeingMapped(mappingExpressions, ctx))
                {
                    ctx.MappingExpressions.RemoveRange(mappingExpressionCount, addedExpressionCount);
                }
            });
        }
示例#8
0
        protected override IEnumerable <Expression> GetObjectPopulation(MappingCreationContext context)
        {
            Expression population;

            if (!context.MapperData.TargetMember.IsDictionary)
            {
                population = GetDictionaryPopulation(context.MappingData);
                goto ReturnPopulation;
            }

            var assignmentFactory = GetDictionaryAssignmentFactoryOrNull(context, out var useAssignmentOnly);

            if (useAssignmentOnly)
            {
                yield return(assignmentFactory.Invoke(context.MappingData));

                yield break;
            }

            population = GetDictionaryPopulation(context.MappingData);
            var assignment = assignmentFactory?.Invoke(context.MappingData);

            if (assignment != null)
            {
                yield return(assignment);
            }

ReturnPopulation:
            if (population != null)
            {
                yield return(population);
            }
        }
示例#9
0
        protected override IEnumerable <Expression> GetObjectPopulation(MappingCreationContext context)
        {
            var mapperData  = context.MapperData;
            var enumMapping = mapperData.GetValueConversion(mapperData.SourceObject, mapperData.TargetType);

            yield return(context.MapperData.LocalVariable.AssignTo(enumMapping));
        }
示例#10
0
        private static Func <IObjectMappingData, Expression> GetDictionaryAssignmentFactoryOrNull(
            MappingCreationContext context,
            out bool useAssignmentOnly)
        {
            if (!context.InstantiateLocalVariable || context.MapperData.TargetMember.IsReadOnly)
            {
                useAssignmentOnly = false;
                return(null);
            }

            var mapperData = context.MapperData;

            if (SourceMemberIsDictionary(mapperData, out var sourceDictionaryMember))
            {
                if (UseDictionaryCloneConstructor(sourceDictionaryMember, mapperData, out var cloneConstructor))
                {
                    useAssignmentOnly = true;
                    return(md => GetClonedDictionaryAssignment(md.MapperData, cloneConstructor));
                }

                useAssignmentOnly = false;
                return(md => GetMappedDictionaryAssignment(sourceDictionaryMember, md));
            }

            useAssignmentOnly = false;
            return(GetParameterlessDictionaryAssignment);
        }
示例#11
0
 private static Expression GetReturnExpression(Expression returnValue, MappingCreationContext context)
 {
     return((context.MapToNullCondition != null)
         ? Expression.Condition(
                context.MapToNullCondition,
                returnValue.Type.ToDefaultExpression(),
                returnValue)
         : returnValue);
 }
 private static void AddPopulationsAndCallbacks <TArg>(
     TArg argument,
     MappingCreationContext context,
     Action <TArg, MappingCreationContext> mappingBodyPopulator)
 {
     context.MappingExpressions.AddUnlessNullOrEmpty(context.PreMappingCallback);
     mappingBodyPopulator.Invoke(argument, context);
     context.MappingExpressions.AddUnlessNullOrEmpty(context.PostMappingCallback);
 }
        private static bool NothingIsBeingMapped(
            IList <Expression> mappingExpressions,
            MappingCreationContext context)
        {
            if (mappingExpressions.None())
            {
                return(true);
            }

            if (mappingExpressions[0].NodeType != Assign)
            {
                return(false);
            }

            var assignedValue = ((BinaryExpression)mappingExpressions[0]).Right;

            if (assignedValue.NodeType == Default)
            {
                return(true);
            }

            if (!mappingExpressions.HasOne())
            {
                return(false);
            }

            if (assignedValue == context.MapperData.TargetObject)
            {
                return(true);
            }

            if ((assignedValue.NodeType == New) &&
                context.MapperData.TargetMemberIsEnumerableElement() &&
                ((NewExpression)assignedValue).Arguments.None())
            {
                return(true);
            }

            if (assignedValue.NodeType != Coalesce)
            {
                return(false);
            }

            var valueCoalesce = (BinaryExpression)assignedValue;

            if ((valueCoalesce.Left != context.MapperData.TargetObject) ||
                (valueCoalesce.Right.NodeType != New))
            {
                return(false);
            }

            var objectNewing = (NewExpression)valueCoalesce.Right;

            return(objectNewing.Arguments.None() && (objectNewing.Type != typeof(object)));
        }
        private static Expression GetExpressionToReturn(Expression returnValue, MappingCreationContext context)
        {
            var mapToNullCondition = GetMapToNullConditionOrNull(context);

            return((mapToNullCondition != null)
                ? Expression.Condition(
                       mapToNullCondition,
                       returnValue.Type.ToDefaultExpression(),
                       returnValue)
                : returnValue);
        }
        protected override IEnumerable <Expression> GetObjectPopulation(MappingCreationContext context)
        {
            var mapperData = context.MapperData;

            return(new[]
            {
                mapperData.CanConvert(mapperData.SourceType, mapperData.TargetType)
                    ? mapperData.GetValueConversion(mapperData.SourceObject, mapperData.TargetType)
                    : mapperData.TargetObject
            });
        }
示例#16
0
        private IEnumerable <Expression> GetConfiguredToTargetDataSourceMappings(MappingCreationContext context)
        {
            if (!HasConfiguredToTargetDataSources(context.MapperData, out var configuredToTargetDataSources))
            {
                yield break;
            }

            for (var i = 0; i < configuredToTargetDataSources.Count;)
            {
                var configuredToTargetDataSource = configuredToTargetDataSources[i++];
                var newSourceContext             = context.WithDataSource(configuredToTargetDataSource);

                AddPopulationsAndCallbacks(newSourceContext);

                if (newSourceContext.MappingExpressions.None())
                {
                    continue;
                }

                context.UpdateFrom(newSourceContext);

                var mapping = newSourceContext.MappingExpressions.HasOne()
                    ? newSourceContext.MappingExpressions.First()
                    : Expression.Block(newSourceContext.MappingExpressions);

                mapping = MappingFactory.UseLocalToTargetDataSourceVariableIfAppropriate(
                    context.MapperData,
                    newSourceContext.MapperData,
                    configuredToTargetDataSource.Value,
                    mapping);

                if (!configuredToTargetDataSource.IsConditional)
                {
                    yield return(mapping);

                    continue;
                }

                if (context.MapperData.TargetMember.IsComplex || (i > 1))
                {
                    yield return(Expression.IfThen(configuredToTargetDataSource.Condition, mapping));

                    continue;
                }

                var fallback = context.MapperData.LocalVariable.Type.GetEmptyInstanceCreation(
                    context.TargetMember.ElementType,
                    context.MapperData.EnumerablePopulationBuilder.TargetTypeHelper);

                var assignFallback = context.MapperData.LocalVariable.AssignTo(fallback);

                yield return(Expression.IfThenElse(configuredToTargetDataSource.Condition, mapping, assignFallback));
            }
        }
示例#17
0
        private static bool NothingIsBeingMapped(MappingCreationContext context)
        {
            var mappingExpressions = context
                                     .MappingExpressions
                                     .Filter(IsMemberMapping)
                                     .ToList();

            if (mappingExpressions.None())
            {
                return(true);
            }

            if (mappingExpressions[0].NodeType != Assign)
            {
                return(false);
            }

            var assignedValue = ((BinaryExpression)mappingExpressions[0]).Right;

            if (assignedValue.NodeType == Default)
            {
                return(true);
            }

            if (!mappingExpressions.HasOne())
            {
                return(false);
            }

            if (assignedValue == context.MapperData.TargetObject)
            {
                return(true);
            }

            if (assignedValue.NodeType == Coalesce)
            {
                var valueCoalesce = (BinaryExpression)assignedValue;

                if ((valueCoalesce.Left == context.MapperData.TargetObject) &&
                    (valueCoalesce.Right.NodeType == New))
                {
                    var objectNewing = (NewExpression)valueCoalesce.Right;

                    if (objectNewing.Arguments.None() && (objectNewing.Type != typeof(object)))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public void UpdateFrom(MappingCreationContext childSourceContext)
        {
            MappingData.MapperKey.AddSourceMemberTypeTesterIfRequired(childSourceContext.MappingData);

            if (TargetMember.IsComplex || _mapperDataHasRootEnumerableVariables)
            {
                return;
            }

            _mapperDataHasRootEnumerableVariables = true;

            UpdateEnumerableVariables(childSourceContext.MapperData, MapperData);
        }
        private IEnumerable <Expression> EnumerateShortCircuitReturns(MappingCreationContext context)
        {
            var mappingData = context.MappingData;

            foreach (var shortCircuitFactory in ShortCircuitFactories)
            {
                var shortCircuit = shortCircuitFactory.Invoke(mappingData);

                if (shortCircuit != null)
                {
                    yield return(shortCircuit);
                }
            }
        }
示例#20
0
        private static void AdjustForSingleExpressionBlockIfApplicable(MappingCreationContext context)
        {
            if (!context.MappingExpressions.HasOne() || (context.MappingExpressions[0].NodeType != Block))
            {
                return;
            }

            var block = (BlockExpression)context.MappingExpressions[0];

            if (block.Expressions.HasOne() && block.Variables.None())
            {
                context.MappingExpressions.Clear();
                context.MappingExpressions.AddRange(block.Expressions);
            }
        }
示例#21
0
        private IEnumerable <Expression> GetConfiguredRootDataSourcePopulations(MappingCreationContext context)
        {
            if (!HasConfiguredRootDataSources(context.MapperData, out var configuredRootDataSources))
            {
                yield break;
            }

            for (var i = 0; i < configuredRootDataSources.Count; ++i)
            {
                var configuredRootDataSource = configuredRootDataSources[i];
                var newSourceContext         = context.WithDataSource(configuredRootDataSource);

                var memberPopulations = GetObjectPopulation(newSourceContext).WhereNotNull().ToArray();

                if (memberPopulations.None())
                {
                    continue;
                }

                context.UpdateFrom(newSourceContext);

                var mapping = memberPopulations.HasOne()
                    ? memberPopulations.First()
                    : Expression.Block(memberPopulations);

                if (!configuredRootDataSource.IsConditional)
                {
                    yield return(mapping);

                    continue;
                }

                if (context.MapperData.TargetMember.IsComplex || (i > 0))
                {
                    yield return(Expression.IfThen(configuredRootDataSource.Condition, mapping));

                    continue;
                }

                var fallback = context.MapperData.LocalVariable.Type.GetEmptyInstanceCreation(
                    context.TargetMember.ElementType,
                    context.MapperData.EnumerablePopulationBuilder.TargetTypeHelper);

                var assignFallback = context.MapperData.LocalVariable.AssignTo(fallback);

                yield return(Expression.IfThenElse(configuredRootDataSource.Condition, mapping, assignFallback));
            }
        }
示例#22
0
        private Expression GetMappingBlock(MappingCreationContext context)
        {
            var mappingExpressions = context.MappingExpressions;

            AdjustForSingleExpressionBlockIfApplicable(context);

            if (context.MapperData.UseSingleMappingExpression())
            {
                return(mappingExpressions.First());
            }

            if (mappingExpressions.HasOne() && (mappingExpressions[0].NodeType == Constant))
            {
                goto CreateFullMappingBlock;
            }

            Expression returnExpression;

            if (mappingExpressions[0].NodeType != Block)
            {
                if (mappingExpressions[0].NodeType == MemberAccess)
                {
                    return(GetReturnExpression(mappingExpressions[0], context));
                }

                if (TryAdjustForUnusedLocalVariableIfApplicable(context, out returnExpression))
                {
                    return(returnExpression);
                }
            }
            else if (TryAdjustForUnusedLocalVariableIfApplicable(context, out returnExpression))
            {
                return(returnExpression);
            }

CreateFullMappingBlock:

            returnExpression = GetReturnExpression(GetReturnValue(context.MapperData), context);

            mappingExpressions.Add(context.MapperData.GetReturnLabel(returnExpression));

            var mappingBlock = context.MapperData.Context.UseLocalVariable
                ? Expression.Block(new[] { context.MapperData.LocalVariable }, mappingExpressions)
                : Expression.Block(mappingExpressions);

            return(mappingBlock);
        }
示例#23
0
        public Expression Create(IObjectMappingData mappingData)
        {
            var mapperData = mappingData.MapperData;

            if (TargetCannotBeMapped(mappingData, out var nullMappingBlock))
            {
                return(nullMappingBlock);
            }

            var returnNull = Expression.Return(
                mapperData.ReturnLabelTarget,
                mapperData.TargetType.ToDefaultExpression());

            if (MappingAlwaysBranchesToDerivedType(mappingData, out var derivedTypeMappings))
            {
                var shortCircuitReturns = GetShortCircuitReturns(returnNull, mappingData).ToArray();

                return(shortCircuitReturns.Any()
                    ? Expression.Block(shortCircuitReturns.Append(derivedTypeMappings))
                    : derivedTypeMappings);
            }

            var context = new MappingCreationContext(mappingData);

            context.MappingExpressions.AddUnlessNullOrEmpty(derivedTypeMappings);

            AddPopulationsAndCallbacks(context);

            if (NothingIsBeingMapped(context))
            {
                return(mapperData.IsEntryPoint ? mapperData.TargetObject : Constants.EmptyExpression);
            }

            context.MappingExpressions.InsertRange(0, GetShortCircuitReturns(returnNull, mappingData));

            var mappingBlock = GetMappingBlock(context);

            if (mapperData.Context.UseMappingTryCatch)
            {
                mappingBlock = WrapInTryCatch(mappingBlock, mapperData);
            }

            return(mappingBlock);
        }
        private bool ShortCircuitMapping(MappingCreationContext context)
        {
            foreach (var factory in AlternateMappingFactories)
            {
                var mapping = factory.Invoke(context, out var isConditional);

                if (mapping == null)
                {
                    continue;
                }

                if (context.MappingComplete)
                {
                    InsertShortCircuitReturns(context);

                    var returnLabel = context.MapperData
                                      .GetFinalisedReturnValue(mapping, out var returnsDefault);

                    if (returnsDefault)
                    {
                        context.MappingExpressions.Add(mapping);
                    }

                    context.MappingExpressions.Add(returnLabel);
                    return(true);
                }

                if (isConditional)
                {
                    context.MappingExpressions.Add(mapping);
                    continue;
                }

                AddPopulationsAndCallbacks(
                    mapping,
                    context,
                    (m, ctx) => ctx.MappingExpressions.Add(m));

                return(true);
            }

            return(false);
        }
        public Expression Create(IObjectMappingData mappingData)
        {
            var mapperData = mappingData.MapperData;

            if (TargetCannotBeMapped(mappingData, out var reason))
            {
                return(Expression.Block(
                           ReadableExpression.Comment(reason),
                           GetNullMappingFallbackValue(mapperData)));
            }

            var context = new MappingCreationContext(mappingData);

            if (ShortCircuitMapping(context))
            {
                if (context.MappingComplete)
                {
                    return(context.GetMappingExpression());
                }

                goto CompleteMappingBlock;
            }

            AddPopulationsAndCallbacks(context);

            if (context.RemoveEmptyMappings && NothingIsBeingMapped(context))
            {
                return(mapperData.IsEntryPoint ? mapperData.TargetObject : Constants.EmptyExpression);
            }

CompleteMappingBlock:
            InsertShortCircuitReturns(context);

            var mappingBlock = GetMappingBlock(context);

            if (mapperData.Context.UseMappingTryCatch)
            {
                mappingBlock = mappingBlock.WrapInTryCatch(mapperData);
            }

            return(mappingBlock);
        }
        public void UpdateFrom(MappingCreationContext toTargetContext, IDataSource toTargetDataSource)
        {
            var toTargetMappingData = toTargetContext.MappingData;

            MappingData.MapperKey.AddSourceMemberTypeTesterIfRequired(toTargetMappingData);

            if (!MapperData.IsRoot)
            {
                var dataSourceSet = DataSourceSet.For(toTargetDataSource, toTargetMappingData);
                MapperData.RegisterTargetMemberDataSources(dataSourceSet);
            }

            if (TargetMember.IsComplex)
            {
                UpdateChildMemberDataSources(toTargetContext.MapperData);
                return;
            }

            UpdateEnumerableVariablesIfAppropriate(toTargetContext.MapperData, MapperData);
        }
        private Expression GetConfiguredAlternateDataSourceMappingOrNull(
            MappingCreationContext context,
            out bool isConditional)
        {
            var toTargetDataSource = context
                                     .ToTargetDataSources
                                     .FirstOrDefault(ds => !ds.IsSequential && !ds.HasConfiguredMatcher);

            if (toTargetDataSource == null)
            {
                isConditional = false;
                return(null);
            }

            isConditional = toTargetDataSource.HasConfiguredCondition;

            return(GetConfiguredToTargetDataSourceMappingOrNull(
                       context,
                       toTargetDataSource,
                       isFirstDataSource: true));
        }
        private Expression GetMappingBlock(MappingCreationContext context)
        {
            var mappingExpressions = context.MappingExpressions;

            AdjustForSingleExpressionBlockIfApplicable(context);

            var firstExpression = mappingExpressions.First();

            if (firstExpression.NodeType == Goto)
            {
                return(((GotoExpression)firstExpression).Value);
            }

            if (context.MapperData.UseSingleMappingExpression())
            {
                return(firstExpression);
            }

            Expression returnExpression;

            if (firstExpression.NodeType != Block)
            {
                if (TryAdjustForUnusedLocalVariableIfApplicable(context, out returnExpression))
                {
                    return(returnExpression);
                }
            }
            else if (TryAdjustForUnusedLocalVariableIfApplicable(context, out returnExpression))
            {
                return(returnExpression);
            }

            mappingExpressions.Add(context.MapperData.GetReturnLabel(GetExpressionToReturn(context)));

            var mappingBlock = context.MapperData.Context.UseLocalVariable
                ? Expression.Block(new[] { context.MapperData.LocalVariable }, mappingExpressions)
                : mappingExpressions.ToExpression();

            return(mappingBlock);
        }
        private static bool TryAdjustForUnusedLocalVariableIfApplicable(MappingCreationContext context, out Expression returnExpression)
        {
            if (!context.MapperData.Context.UseLocalVariable)
            {
                returnExpression = null;
                return(false);
            }

            var mappingExpressions = context.MappingExpressions;

            if (!mappingExpressions.TryGetVariableAssignment(out var localVariableAssignment))
            {
                returnExpression = null;
                return(false);
            }

            if ((localVariableAssignment.Left.NodeType != Parameter) ||
                (localVariableAssignment != mappingExpressions.Last()))
            {
                returnExpression = null;
                return(false);
            }

            var assignedValue = localVariableAssignment.Right;

            returnExpression = (assignedValue.NodeType == Invoke)
                ? Expression.Block(
                new[] { (ParameterExpression)localVariableAssignment.Left },
                GetExpressionToReturn(localVariableAssignment, context))
                : GetExpressionToReturn(assignedValue, context);

            if (mappingExpressions.HasOne())
            {
                return(true);
            }

            mappingExpressions[mappingExpressions.Count - 1] = context.MapperData.GetReturnLabel(returnExpression);
            returnExpression = Expression.Block(mappingExpressions);
            return(true);
        }
        public MappingCreationContext WithDataSource(IDataSource newDataSource)
        {
            var newSourceMappingData = MappingData.WithSource(newDataSource.SourceMember);

            var newContext = new MappingCreationContext(newSourceMappingData)
            {
                InstantiateLocalVariable = false
            };

            newContext.MapperData.SourceObject = newDataSource.Value;
            newContext.MapperData.TargetObject = MapperData.TargetObject;

            if (TargetMember.IsComplex)
            {
                newContext.MapperData.TargetInstance = MapperData.TargetInstance;
            }
            else if (_mapperDataHasRootEnumerableVariables)
            {
                UpdateEnumerableVariables(MapperData, newContext.MapperData);
            }

            return(newContext);
        }