Mapping MemberInit expressions fail for custom MapFrom expressions.
Apolloangel opened this issue · 3 comments
Apolloangel commented
The issue I'm currently facing is that I have a Select expression based on a model (DTO) where some of the selected properties are part of a SubObject. when I try to map this expression to an expression to another model (DB). Here are the classes and im using.
All samplecode shown here attached.
SampleProject.zip
public class PlayerDbEntry
{
public string? Key { get; set; }
public string? Name { get; set; }
public ClubDb? Club { get; set; }
}
public class ClubDb
{
public string? Name { get; set; }
}
public class PlayerDToEntry
{
public string? Key { get; set; }
public string? PlayerName { get; set; }
public ClubDto? ClubDto { get; set; }
}
public class ClubDto
{
public string? ClubNameName { get; set; }
}
public class PlayerProfile : Profile
{
public PlayerProfile()
{
CreateMap<PlayerDbEntry, PlayerDToEntry>()
.ForMember(dest => dest.PlayerName, opt =>
{
opt.MapFrom(src => src.Name);
opt.ExplicitExpansion();
})
.ForMember(dest => dest.ClubDto, opt =>
{
opt.MapFrom(src => src.Club);
opt.ExplicitExpansion();
})
.ForMember(dest => dest.Key, opt => opt.MapFrom(src => src.Key));
CreateMap<PlayerDToEntry, PlayerDbEntry>()
.ForMember(dest => dest.Name, opt =>
{
opt.MapFrom(src => src.PlayerName);
opt.ExplicitExpansion();
})
.ForMember(dest => dest.Club, opt =>
{
opt.MapFrom(src => src.ClubDto);
opt.ExplicitExpansion();
})
.ForMember(dest => dest.Key, opt => opt.MapFrom(src => src.Key));
CreateMap<ClubDb, ClubDto>()
.ForMember(dest => dest.ClubNameName, opt => opt.MapFrom(src => src.Name))
.ReverseMap();
}
}
When i run the following code:
var config = new MapperConfiguration(cfg =>
{
cfg.AddExpressionMapping();
cfg.AddMaps(typeof(PlayerProfile));
});
var mapper = config.CreateMapper();
Expression<Func<PlayerDToEntry, PlayerDToEntry>> expression = (e) => new PlayerDToEntry
{
PlayerName = e.PlayerName,
ClubDto = new ClubDto
{
ClubNameName = e.ClubDto!.ClubNameName
}
};
try
{
var dbExpression = mapper.MapExpression<Expression<Func<PlayerDbEntry, PlayerDbEntry>>>(expression);
}
catch (Exception e)
{
Console.WriteLine(e);
}
I encounter the exception below. the issue issue seems to be with the mapping between the SubObjects, any idear as to what could cause the issue?
System.InvalidOperationException: No coercion operator is defined between types 'SampleProject.ClubDto' and 'SampleProject.ClubDb'.
at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type)
at AutoMapper.Extensions.ExpressionMapping.Extensions.VisitorExtensions.ConvertTypeIfNecessary(Expression expression, Type memberType)
at AutoMapper.Extensions.ExpressionMapping.XpressionMapperVisitor.DoBind(MemberInfo sourceMember, Expression initial, Expression mapped)
at AutoMapper.Extensions.ExpressionMapping.XpressionMapperVisitor.<>c__DisplayClass27_0.<GetMemberInit>b__0(List`1 list, MemberAssignmentInfo next)
at System.Linq.Enumerable.Aggregate[TSource,TAccumulate](IEnumerable`1 source, TAccumulate seed, Func`3 func)
at AutoMapper.Extensions.ExpressionMapping.XpressionMapperVisitor.GetMemberInit(MemberBindingGroup memberBindingGroup)
at AutoMapper.Extensions.ExpressionMapping.XpressionMapperVisitor.VisitMemberInit(MemberInitExpression node)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at AutoMapper.Extensions.ExpressionMapping.MapperExtensions.<MapExpression>g__MapBody|8_1[TDestDelegate](Dictionary`2 typeMappings, XpressionMapperVisitor visitor, <>c__DisplayClass8_0`1& )
at AutoMapper.Extensions.ExpressionMapping.MapperExtensions.<MapExpression>g__CreateVisitor|8_0[TDestDelegate](Dictionary`2 typeMappings, <>c__DisplayClass8_0`1& )
at AutoMapper.Extensions.ExpressionMapping.MapperExtensions.MapExpression[TDestDelegate](IConfigurationProvider configurationProvider, LambdaExpression expression, Type typeSourceFunc, Type typeDestFunc, Func`3 getVisitor, Func`2 shouldConvertMappedBodyToDestType)
at AutoMapper.Extensions.ExpressionMapping.MapperExtensions.MapExpression[TDestDelegate](IMapper mapper, LambdaExpression expression, Func`3 getVisitor, Func`2 shouldConvertMappedBodyToDestType)
at AutoMapper.Extensions.ExpressionMapping.MapperExtensions.MapExpression[TDestDelegate](IMapper mapper, LambdaExpression expression)
at Program.<Main>$(String[] args)
BlaiseD commented
Yep - there was a bug - it was failing for custom expressions. The MyGet build should work now. Thanks for reporting.
Apolloangel commented
Thanks that solved my issue :)
Any idea about when this will be part of an official release?