Skip to content

Commit 1922bce

Browse files
authored
Merge pull request #49 from BlaiseD/master
Fix InvalidOperationException mapping nested lambda expressions. Fixes Issues #48.
2 parents 73adfdf + 87c0a33 commit 1922bce

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<Authors>Jimmy Bogard</Authors>
44
<LangVersion>latest</LangVersion>
5-
<VersionPrefix>3.0.3</VersionPrefix>
5+
<VersionPrefix>3.0.4-preview01</VersionPrefix>
66
<WarningsAsErrors>true</WarningsAsErrors>
77
<NoWarn>$(NoWarn);1701;1702;1591</NoWarn>
88
</PropertyGroup>

src/AutoMapper.Extensions.ExpressionMapping/MapperExtensions.cs

+27
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,33 @@ public static Dictionary<Type, Type> AddTypeMapping(this Dictionary<Type, Type>
278278
return typeMappings;
279279
}
280280

281+
/// <summary>
282+
/// Replaces a type in the source expression with the corresponding destination type.
283+
/// </summary>
284+
/// <param name="typeMappings"></param>
285+
/// <param name="sourceType"></param>
286+
/// <returns></returns>
287+
public static Type ReplaceType(this Dictionary<Type, Type> typeMappings, Type sourceType)
288+
{
289+
if (!sourceType.IsGenericType)
290+
{
291+
return typeMappings.TryGetValue(sourceType, out Type destType) ? destType : sourceType;
292+
}
293+
else
294+
{
295+
if (typeMappings.TryGetValue(sourceType, out Type destType))
296+
return destType;
297+
else
298+
return sourceType.GetGenericTypeDefinition().MakeGenericType
299+
(
300+
sourceType
301+
.GetGenericArguments()
302+
.Select(type => typeMappings.ReplaceType(type))
303+
.ToArray()
304+
);
305+
}
306+
}
307+
281308
private static Dictionary<Type, Type> AddTypeMappingsFromDelegates(this Dictionary<Type, Type> typeMappings, IConfigurationProvider configurationProvider, Type sourceType, Type destType)
282309
{
283310
if (typeMappings == null)

src/AutoMapper.Extensions.ExpressionMapping/XpressionMapperVisitor.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ protected override Expression VisitLambda<T>(Expression<T> node)
124124
{
125125
var ex = this.Visit(node.Body);
126126

127-
var mapped = Expression.Lambda(ex, node.GetDestinationParameterExpressions(this.InfoDictionary, this.TypeMappings));
127+
var mapped = Expression.Lambda(this.TypeMappings.ReplaceType(node.Type), ex, node.GetDestinationParameterExpressions(this.InfoDictionary, this.TypeMappings));
128128
this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, mapped.Type);
129129
return mapped;
130130
}
@@ -214,7 +214,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
214214

215215
//type args are the generic type args e.g. T1 and T2 MethodName<T1, T2>(method arguments);
216216
var typeArgsForNewMethod = node.Method.IsGenericMethod
217-
? node.Method.GetGenericArguments().Select(i => TypeMappings.ContainsKey(i) ? TypeMappings[i] : i).ToList()//not converting the type it is not in the typeMappings dictionary
217+
? node.Method.GetGenericArguments().Select(type => this.TypeMappings.ReplaceType(type)).ToList()//not converting the type it is not in the typeMappings dictionary
218218
: null;
219219

220220
ConvertTypesIfNecessary(node.Method.GetParameters(), listOfArgumentsForNewMethod, node.Method);

tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/XpressionMapperTests.cs

+13
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,19 @@ public void Map_orderBy_thenBy_GroupBy_Select_expression()
469469
Assert.True(users[0].Count == 2);
470470
}
471471

472+
[Fact]
473+
public void Map_orderBy_thenBy_GroupBy_SelectMany_expression()
474+
{
475+
//Arrange
476+
Expression<Func<IQueryable<UserModel>, IQueryable<UserModel>>> grouped = q => q.OrderBy(s => s.Id).ThenBy(s => s.FullName).GroupBy(s => s.AgeInYears).SelectMany(grp => grp);
477+
478+
//Act
479+
Expression<Func<IQueryable<User>, IQueryable<User>>> expMapped = mapper.MapExpression<Expression<Func<IQueryable<User>, IQueryable<User>>>>(grouped);
480+
List<User> users = expMapped.Compile().Invoke(Users).ToList();
481+
482+
Assert.True(users.Count == 2);
483+
}
484+
472485
[Fact]
473486
public void Map_orderBy_thenBy_To_Dictionary_Select_expression()
474487
{

0 commit comments

Comments
 (0)