@@ -127,22 +127,16 @@ public Expression CreateMapExpression(ExpressionRequest request, Expression inst
127127
128128 private Expression CreateMapExpressionCore ( ExpressionRequest request , Expression instanceParameter , TypePairCount typePairCount , LetPropertyMaps letPropertyMaps , out TypeMap typeMap )
129129 {
130- typeMap = _configurationProvider . ResolveTypeMap ( request . SourceType , request . DestinationType ) ;
131-
132- if ( typeMap == null )
133- {
134- throw QueryMapperHelper . MissingMapException ( request . SourceType , request . DestinationType ) ;
135- }
136-
137- if ( typeMap . CustomMapExpression != null )
138- {
139- return typeMap . CustomMapExpression . ReplaceParameters ( instanceParameter ) ;
140- }
130+ typeMap = _configurationProvider . ResolveTypeMap ( request . SourceType , request . DestinationType ) ?? throw QueryMapperHelper . MissingMapException ( request . SourceType , request . DestinationType ) ;
141131 return CreateMapExpressionCore ( request , instanceParameter , typePairCount , typeMap , letPropertyMaps ) ;
142132 }
143133
144134 private Expression CreateMapExpressionCore ( ExpressionRequest request , Expression instanceParameter , TypePairCount typePairCount , TypeMap typeMap , LetPropertyMaps letPropertyMaps )
145135 {
136+ if ( typeMap . CustomMapExpression != null )
137+ {
138+ return typeMap . CustomMapExpression . ReplaceParameters ( instanceParameter ) ;
139+ }
146140 var memberBindings = new List < MemberBinding > ( ) ;
147141 var depth = GetDepth ( request , typePairCount ) ;
148142 if ( typeMap . MaxDepth > 0 && depth >= typeMap . MaxDepth )
@@ -156,16 +150,9 @@ private Expression CreateMapExpressionCore(ExpressionRequest request, Expression
156150 {
157151 memberBindings = CreateMemberBindings ( ) ;
158152 }
159- Expression constructorExpression = DestinationConstructorExpression ( typeMap , instanceParameter , letPropertyMaps ) ;
160- if ( instanceParameter is ParameterExpression )
161- constructorExpression = ( ( LambdaExpression ) constructorExpression ) . ReplaceParameters ( instanceParameter ) ;
162- var visitor = new NewFinderVisitor ( ) ;
163- visitor . Visit ( constructorExpression ) ;
164-
165- var expression = MemberInit (
166- visitor . NewExpression ,
167- memberBindings . ToArray ( )
168- ) ;
153+ var constructorExpressionLambda = DestinationConstructorExpression ( request , instanceParameter , typePairCount , typeMap , letPropertyMaps ) ;
154+ var constructorExpression = instanceParameter is ParameterExpression ? constructorExpressionLambda . ReplaceParameters ( instanceParameter ) : constructorExpressionLambda . Body ;
155+ var expression = MemberInit ( ( NewExpression ) constructorExpression , memberBindings ) ;
169156 return expression ;
170157 List < MemberBinding > CreateMemberBindings ( )
171158 {
@@ -197,9 +184,8 @@ void CreateMemberBinding(PropertyExpression propertyExpression)
197184 var binder = _configurationProvider . Binders . FirstOrDefault ( b => b . IsMatch ( propertyMap , propertyTypeMap , result ) ) ;
198185 if ( binder == null )
199186 {
200- var message =
201- $ "Unable to create a map expression from { propertyMap . SourceMember ? . DeclaringType ? . Name } .{ propertyMap . SourceMember ? . Name } ({ result . Type } ) to { propertyMap . DestinationMember . DeclaringType ? . Name } .{ propertyMap . DestinationName } ({ propertyMap . DestinationType } )";
202- throw new AutoMapperMappingException ( message , null , typeMap . Types , typeMap , propertyMap ) ;
187+ ThrowCannotMap ( propertyMap , result ) ;
188+ return ;
203189 }
204190 var bindExpression = binder . Build ( _configurationProvider , propertyMap , propertyTypeMap , propertyRequest , result , typePairCount , letPropertyMaps ) ;
205191 if ( bindExpression == null )
@@ -219,6 +205,13 @@ void CreateMemberBinding(PropertyExpression propertyExpression)
219205 }
220206 }
221207
208+ private static void ThrowCannotMap ( IMemberMap propertyMap , ExpressionResolutionResult result )
209+ {
210+ var message =
211+ $ "Unable to create a map expression from { propertyMap . SourceMember ? . DeclaringType ? . Name } .{ propertyMap . SourceMember ? . Name } ({ result . Type } ) to { propertyMap . DestinationType . Name } .{ propertyMap . DestinationName } ({ propertyMap . DestinationType } )";
212+ throw new AutoMapperMappingException ( message , null , propertyMap . TypeMap . Types , propertyMap . TypeMap , propertyMap ) ;
213+ }
214+
222215 private static int GetDepth ( ExpressionRequest request , TypePairCount typePairCount )
223216 {
224217 if ( typePairCount . TryGetValue ( request , out int visitCount ) )
@@ -229,39 +222,51 @@ private static int GetDepth(ExpressionRequest request, TypePairCount typePairCou
229222 return visitCount ;
230223 }
231224
232- private LambdaExpression DestinationConstructorExpression ( TypeMap typeMap , Expression instanceParameter , LetPropertyMaps letPropertyMaps )
225+ private LambdaExpression DestinationConstructorExpression ( ExpressionRequest request , Expression instanceParameter , TypePairCount typePairCount , TypeMap typeMap , LetPropertyMaps letPropertyMaps )
233226 {
234227 var ctorExpr = typeMap . CustomCtorExpression ;
235228 if ( ctorExpr != null )
236229 {
237230 return ctorExpr ;
238231 }
239232 var newExpression = typeMap . ConstructorMap ? . CanResolve == true
240- ? typeMap . ConstructorMap . NewExpression ( instanceParameter , letPropertyMaps )
233+ ? NewExpression ( typeMap . ConstructorMap , request , instanceParameter , typePairCount , letPropertyMaps )
241234 : New ( typeMap . DestinationTypeToUse ) ;
242-
243235 return Lambda ( newExpression ) ;
244236 }
245237
246- private class NewFinderVisitor : ExpressionVisitor
247- {
248- public NewExpression NewExpression { get ; private set ; }
249238
250- protected override Expression VisitNew ( NewExpression node )
239+ public Expression NewExpression ( ConstructorMap constructorMap , ExpressionRequest request , Expression instanceParameter , TypePairCount typePairCount , LetPropertyMaps letPropertyMaps )
240+ {
241+ var parameters = constructorMap . CtorParams . Select ( map =>
251242 {
252- NewExpression = node ;
253- return base . VisitNew ( node ) ;
254- }
243+ var resolvedSource = ResolveExpression ( map , request . SourceType , instanceParameter , letPropertyMaps ) ;
244+ var types = new TypePair ( resolvedSource . Type , map . DestinationType ) ;
245+ var typeMap = _configurationProvider . ResolveTypeMap ( types ) ;
246+ if ( typeMap == null )
247+ {
248+ if ( types . DestinationType . IsAssignableFrom ( types . SourceType ) )
249+ {
250+ return resolvedSource . ResolutionExpression ;
251+ }
252+ ThrowCannotMap ( map , resolvedSource ) ;
253+ }
254+ var newRequest = new ExpressionRequest ( types . SourceType , types . DestinationType , request . MembersToExpand , request ) ;
255+ return CreateMapExpressionCore ( newRequest , resolvedSource . ResolutionExpression , typePairCount , typeMap , letPropertyMaps ) ;
256+ } ) ;
257+ return New ( constructorMap . Ctor , parameters ) ;
255258 }
256259
257- private ExpressionResolutionResult ResolveExpression ( PropertyMap propertyMap , Type currentType , Expression instanceParameter , LetPropertyMaps letPropertyMaps )
260+ private ExpressionResolutionResult ResolveExpression ( IMemberMap propertyMap , Type currentType , Expression instanceParameter , LetPropertyMaps letPropertyMaps )
258261 {
259262 var result = new ExpressionResolutionResult ( instanceParameter , currentType ) ;
260-
261263 var matchingExpressionConverter = _configurationProvider . ResultConverters . FirstOrDefault ( c => c . CanGetExpressionResolutionResult ( result , propertyMap ) ) ;
262- result = matchingExpressionConverter ? . GetExpressionResolutionResult ( result , propertyMap , letPropertyMaps )
263- ?? throw new Exception ( "Can't resolve this to Queryable Expression" ) ;
264-
264+ if ( matchingExpressionConverter == null )
265+ {
266+ ThrowCannotMap ( propertyMap , result ) ;
267+ return null ;
268+ }
269+ result = matchingExpressionConverter . GetExpressionResolutionResult ( result , propertyMap , letPropertyMaps ) ;
265270 if ( propertyMap . NullSubstitute != null && result . Type . IsNullableType ( ) )
266271 {
267272 var currentChild = result . ResolutionExpression ;
0 commit comments