Skip to content

Commit 6d3b6ae

Browse files
authored
Merge pull request #4577 from LuckyPennySoftware/4563-provide-better-diagnostic-exceptions-for-expression-tree-errors
Provide better exceptions for errors when building the mapping plan
2 parents a4134df + b1d214e commit 6d3b6ae

File tree

4 files changed

+64
-18
lines changed

4 files changed

+64
-18
lines changed

src/AutoMapper/Execution/TypeMapPlanBuilder.cs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,14 @@ private void AddPathMaps(List<Expression> actions)
254254
continue;
255255
}
256256

257-
actions.Add(TryPathMap(pathMap));
257+
try
258+
{
259+
actions.Add(TryPathMap(pathMap));
260+
}
261+
catch (Exception e) when (e is not AutoMapperConfigurationException)
262+
{
263+
throw new AutoMapperMappingException("Error building path mapping strategy.", e, pathMap);
264+
}
258265
}
259266
}
260267

@@ -287,14 +294,21 @@ private void AddPropertyMaps(List<Expression> actions)
287294
continue;
288295
}
289296

290-
var property = TryMemberMap(propertyMap,
291-
CreatePropertyMapFunc(propertyMap, _destination, propertyMap.DestinationMember));
292-
if (_typeMap.ConstructorParameterMatches(propertyMap.DestinationName))
297+
try
293298
{
294-
property = _initialDestination.IfNullElse(_configuration.Default(property.Type), property);
299+
var property = TryMemberMap(propertyMap,
300+
CreatePropertyMapFunc(propertyMap, _destination, propertyMap.DestinationMember));
301+
if (_typeMap.ConstructorParameterMatches(propertyMap.DestinationName))
302+
{
303+
property = _initialDestination.IfNullElse(_configuration.Default(property.Type), property);
304+
}
305+
306+
actions.Add(property);
307+
}
308+
catch (Exception e) when (e is not AutoMapperConfigurationException)
309+
{
310+
throw new AutoMapperMappingException("Error building member mapping strategy.", e, propertyMap);
295311
}
296-
297-
actions.Add(property);
298312
}
299313
}
300314

@@ -366,9 +380,16 @@ private Expression ConstructorMapping(ConstructorMap constructorMap)
366380
List<Expression> body = [];
367381
foreach (var parameter in constructorMap.CtorParams)
368382
{
369-
var variable = Variable(parameter.DestinationType, parameter.DestinationName);
370-
variables.Add(variable);
371-
body.Add(Assign(variable, CreateConstructorParameterExpression(parameter)));
383+
try
384+
{
385+
var variable = Variable(parameter.DestinationType, parameter.DestinationName);
386+
variables.Add(variable);
387+
body.Add(Assign(variable, CreateConstructorParameterExpression(parameter)));
388+
}
389+
catch (Exception e) when (e is not AutoMapperConfigurationException)
390+
{
391+
throw new AutoMapperMappingException("Error building constructor parameter mapping strategy.", e, parameter);
392+
}
372393
}
373394

374395
body.Add(CheckReferencesCache(New(constructorMap.Ctor, variables)));

src/AutoMapper/QueryableExtensions/ProjectionBuilder.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,18 @@ void ProjectProperties()
110110
{
111111
continue;
112112
}
113-
var propertyProjection = TryProjectMember(propertyMap);
114-
if(propertyProjection != null)
113+
114+
try
115115
{
116-
propertiesProjections.Add(Bind(propertyMap.DestinationMember, propertyProjection));
116+
var propertyProjection = TryProjectMember(propertyMap);
117+
if(propertyProjection != null)
118+
{
119+
propertiesProjections.Add(Bind(propertyMap.DestinationMember, propertyProjection));
120+
}
121+
}
122+
catch (Exception e) when (e is not AutoMapperConfigurationException)
123+
{
124+
throw new AutoMapperMappingException("Error building queryable mapping strategy.", e, propertyMap);
117125
}
118126
}
119127
}
@@ -209,7 +217,17 @@ IProjectionMapper GetProjectionMapper()
209217
{
210218
{ CustomCtorExpression: LambdaExpression ctorExpression } => (NewExpression)ctorExpression.ReplaceParameters(instanceParameter),
211219
{ ConstructorMap: { CanResolve: true } constructorMap } =>
212-
New(constructorMap.Ctor, constructorMap.CtorParams.Select(map => TryProjectMember(map, map.DefaultValue(null)) ?? Default(map.DestinationType))),
220+
New(constructorMap.Ctor, constructorMap.CtorParams.Select(map =>
221+
{
222+
try
223+
{
224+
return TryProjectMember(map, map.DefaultValue(null)) ?? Default(map.DestinationType);
225+
}
226+
catch (Exception e) when (e is not AutoMapperConfigurationException)
227+
{
228+
throw new AutoMapperMappingException("Error building constructor projection strategy.", e, map);
229+
}
230+
})),
213231
_ => New(typeMap.DestinationType)
214232
};
215233
}

src/AutoMapper/TypeMap.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,15 @@ public void Seal(IGlobalConfiguration configuration)
204204
return;
205205
}
206206
_sealed = true;
207-
_details?.Seal(configuration, this);
208-
MapExpression = Projection ? EmptyLambda : CreateMapperLambda(configuration);
207+
try
208+
{
209+
_details?.Seal(configuration, this);
210+
MapExpression = Projection ? EmptyLambda : CreateMapperLambda(configuration);
211+
}
212+
catch (Exception e) when (e is not AutoMapperConfigurationException)
213+
{
214+
throw new AutoMapperMappingException("Error creating mapping strategy.", e, this);
215+
}
209216
SourceTypeDetails = null;
210217
DestinationTypeDetails = null;
211218
}

src/UnitTests/ForPath.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ public class SourceModel
250250
[Fact]
251251
public void Should_throw_exception()
252252
{
253-
Assert.Throws<NullReferenceException>(() =>
253+
Assert.Throws<AutoMapperMappingException>(() =>
254254
{
255255
var cfg = new MapperConfiguration(config =>
256256
{
257-
Assert.Throws<System.ArgumentNullException>(() =>
257+
Assert.Throws<ArgumentNullException>(() =>
258258
{
259259
config.CreateMap<SourceModel, DestinationModel>()
260260
.ForPath(sourceModel => sourceModel.Name, opts => opts.MapFrom<string>(null));

0 commit comments

Comments
 (0)