protected virtual MappingElement TryToCreateMappingExpression(MappingElement source, ITypeSymbol targetType, MappingPath mappingPath) { //TODO: If source expression is method or constructor invocation then we should extract local variable and use it im mappings as a reference var namedTargetType = targetType as INamedTypeSymbol; if (namedTargetType != null) { var directlyMappingConstructor = namedTargetType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type.Equals(source.ExpressionType)); if (directlyMappingConstructor != null) { var constructorParameters = SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(source.Expression)); var creationExpression = syntaxGenerator.ObjectCreationExpression(targetType, constructorParameters.Arguments); return(new MappingElement() { ExpressionType = targetType, Expression = (ExpressionSyntax)creationExpression }); } } if (MappingHelper.IsMappingBetweenCollections(targetType, source.ExpressionType)) { return(new MappingElement() { ExpressionType = targetType, Expression = MapCollections(source.Expression, source.ExpressionType, targetType, mappingPath.Clone()) as ExpressionSyntax }); } var subMappingSourceFinder = new ObjectMembersMappingSourceFinder(source.ExpressionType, source.Expression, syntaxGenerator); if (namedTargetType != null) { //maybe there is constructor that accepts parameter matching source properties var constructorOverloadParameterSets = namedTargetType.Constructors.Select(x => x.Parameters); var matchedOverload = MethodHelper.FindBestParametersMatch(subMappingSourceFinder, constructorOverloadParameterSets); if (matchedOverload != null) { var creationExpression = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType, matchedOverload.ToArgumentListSyntax(this).Arguments)); var matchedSources = matchedOverload.GetMatchedSources(); var restSourceFinder = new IgnorableMappingSourceFinder(subMappingSourceFinder, foundElement => { return(matchedSources.Any(x => x.Expression.IsEquivalentTo(foundElement.Expression))); }); var mappingMatcher = new SingleSourceMatcher(restSourceFinder); return(new MappingElement() { ExpressionType = targetType, Expression = AddInitializerWithMapping(creationExpression, mappingMatcher, targetType, mappingPath) }); } } var objectCreationExpressionSyntax = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType)); var subMappingMatcher = new SingleSourceMatcher(subMappingSourceFinder); return(new MappingElement() { ExpressionType = targetType, Expression = AddInitializerWithMapping(objectCreationExpressionSyntax, subMappingMatcher, targetType, mappingPath) }); }
protected virtual async Task <MappingElement> TryToCreateMappingExpression(MappingElement source, AnnotatedType targetType, MappingPath mappingPath, MappingContext mappingContext) { //TODO: If source expression is method or constructor invocation then we should extract local variable and use it im mappings as a reference var namedTargetType = targetType.Type as INamedTypeSymbol; if (namedTargetType != null) { var directlyMappingConstructor = namedTargetType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type.Equals(source.ExpressionType.Type)); if (directlyMappingConstructor != null) { var creationExpression = CreateObject(targetType.Type, SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(source.Expression))); var shouldProtectAgainstNull = directlyMappingConstructor.Parameters[0].Type.CanBeNull() == false && source.ExpressionType.CanBeNull; return(new MappingElement { ExpressionType = targetType, Expression = shouldProtectAgainstNull ? HandleSafeNull(source, targetType, creationExpression) : creationExpression }); } } if (MappingHelper.IsMappingBetweenCollections(targetType.Type, source.ExpressionType.Type)) { var shouldProtectAgainstNull = source.ExpressionType.CanBeNull && targetType.CanBeNull == false; var collectionMapping = (await MapCollectionsAsync(source, targetType, mappingPath.Clone(), mappingContext).ConfigureAwait(false)) as ExpressionSyntax; return(new MappingElement { ExpressionType = targetType, Expression = shouldProtectAgainstNull ? OrFailWhenArgumentNull(collectionMapping, source.Expression.ToFullString()) : collectionMapping, }); } var subMappingSourceFinder = new ObjectMembersMappingSourceFinder(source.ExpressionType.AsNotNull(), source.Expression); if (namedTargetType != null) { //maybe there is constructor that accepts parameter matching source properties var constructorOverloadParameterSets = namedTargetType.Constructors.Select(x => x.Parameters); var matchedOverload = await MethodHelper.FindBestParametersMatch(subMappingSourceFinder, constructorOverloadParameterSets, mappingContext).ConfigureAwait(false); if (matchedOverload != null) { var argumentListSyntaxAsync = await matchedOverload.ToArgumentListSyntaxAsync(this, mappingContext).ConfigureAwait(false); var creationExpression = CreateObject(targetType.Type, argumentListSyntaxAsync); var matchedSources = matchedOverload.GetMatchedSources(); var restSourceFinder = new IgnorableMappingSourceFinder(subMappingSourceFinder, foundElement => { return(matchedSources.Any(x => x.Expression.IsEquivalentTo(foundElement.Expression))); }); var mappingMatcher = new SingleSourceMatcher(restSourceFinder); return(new MappingElement() { ExpressionType = new AnnotatedType(targetType.Type), Expression = await AddInitializerWithMappingAsync(creationExpression, mappingMatcher, targetType.Type, mappingContext, mappingPath).ConfigureAwait(false), }); } } var objectCreationExpressionSyntax = CreateObject(targetType.Type); var subMappingMatcher = new SingleSourceMatcher(subMappingSourceFinder); var objectCreationWithInitializer = await AddInitializerWithMappingAsync(objectCreationExpressionSyntax, subMappingMatcher, targetType.Type, mappingContext, mappingPath).ConfigureAwait(false); return(new MappingElement() { ExpressionType = new AnnotatedType(targetType.Type), Expression = HandleSafeNull(source, targetType, objectCreationWithInitializer) }); }