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