Skip to content

Commit 17d5804

Browse files
authored
Merge pull request #91 from mycroes/generic-source-type
Fix exceptions with generic source types
2 parents eecf68c + 154c3d8 commit 17d5804

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

src/AutoMapper.Extensions.ExpressionMapping/ExpressionMapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ private Expression VisitAllParametersExpression<T>(Expression<T> expression)
173173
from t in expression.Parameters
174174
let sourceParamType = t.Type
175175
from destParamType in _destSubTypes.Where(dt => dt != sourceParamType)
176-
let a = destParamType.IsGenericType() ? destParamType.GetTypeInfo().GenericTypeArguments[0] : destParamType
176+
let a = destParamType.IsEnumerableType() ? destParamType.GetGenericElementType() : destParamType
177177
let typeMap = _configurationProvider.ResolveTypeMap(a, sourceParamType)
178178
where typeMap != null
179179
let oldParam = t

src/AutoMapper.Extensions.ExpressionMapping/TypeExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,8 @@ public static bool IsQueryableType(this Type type)
171171

172172
public static Type GetGenericElementType(this Type type)
173173
=> type.HasElementType ? type.GetElementType() : type.GetTypeInfo().GenericTypeArguments[0];
174+
175+
public static bool IsEnumerableType(this Type type) =>
176+
type.IsGenericType && typeof(System.Collections.IEnumerable).IsAssignableFrom(type);
174177
}
175178
}

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@ public void When_Apply_Where_Clause_Over_Queryable_As_Data_Source()
4242
result.ShouldAllBe(expOverDTO);
4343
}
4444

45+
[Fact]
46+
public void Should_Map_From_Generic_Type()
47+
{
48+
// Arrange
49+
var mapper = CreateMapper();
50+
51+
var models = new List<GenericModel<bool>>()
52+
{
53+
new GenericModel<bool> {ABoolean = true},
54+
new GenericModel<bool> {ABoolean = false},
55+
new GenericModel<bool> {ABoolean = true},
56+
new GenericModel<bool> {ABoolean = false}
57+
};
58+
59+
var queryable = models.AsQueryable();
60+
61+
Expression<Func<DTO, bool>> expOverDTO = (dto) => dto.Nested.AnotherBoolean;
62+
63+
// Act
64+
var q = queryable.UseAsDataSource(mapper).For<DTO>().Where(expOverDTO);
65+
66+
var result = q.ToList();
67+
68+
// Assert
69+
result.ShouldNotBeNull();
70+
result.Count.ShouldBe(2);
71+
result.ShouldAllBe(expOverDTO);
72+
}
73+
4574
private static IMapper CreateMapper()
4675
{
4776
var mapperConfig = new MapperConfiguration(cfg =>
@@ -52,7 +81,10 @@ private static IMapper CreateMapper()
5281
.ForMember(d => d.AnotherBoolean, opt => opt.MapFrom(s => s.ABoolean));
5382
cfg.CreateMap<DTO, Model>()
5483
.ForMember(d => d.ABoolean, opt => opt.MapFrom(s => s.Nested.AnotherBoolean));
55-
84+
cfg.CreateMap<GenericModel<bool>, DTO>()
85+
.ForMember(d => d.Nested, opt => opt.MapFrom(s => s));
86+
cfg.CreateMap<GenericModel<bool>, DTO.DTONested>()
87+
.ForMember(d => d.AnotherBoolean, opt => opt.MapFrom(s => s.ABoolean));
5688
});
5789

5890
var mapper = mapperConfig.CreateMapper();
@@ -73,5 +105,11 @@ private class Model
73105
{
74106
public bool ABoolean { get; set; }
75107
}
108+
109+
110+
private class GenericModel<T>
111+
{
112+
public T ABoolean { get; set; }
113+
}
76114
}
77115
}

0 commit comments

Comments
 (0)