System.InvalidOperationException: 'Code supposed to be unreachable'



在与AutoMapper团队讨论后,他们建议我把我的问题放在这里。

简而言之,如果我使用

MapExpression<T>(source)

它工作得很好(考虑使用AutoMapper.Extensions.ExpressionMapping框架(。

顺便说一句,作者说我,即使我尝试使用

Map(object, sourceType, targetType) 

它应该正常工作,但是当我使用此方法时,我遇到了本文标题中所述的错误。

为了提供帮助,我写了一个完整的示例,说明如何重现下面的问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using AutoMapper;
using AutoMapper.Extensions.ExpressionMapping;
namespace AutoMapperExpressionMappingTest
{
public class PresentationModelPerson
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
public class ApplicationModelPerson
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
public class DomainModelPerson
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
public class PresentationPerson
{
private readonly IMapper _mapper;
public PresentationPerson(IMapper mapper) => _mapper = mapper;
public  IEnumerable<PresentationModelPerson> List(int take, int skip,
Expression<Func<IQueryable<PresentationModelPerson>, IOrderedQueryable<PresentationModelPerson>>> orderBy,
Expression<Func<PresentationModelPerson, bool>> where, IList<Expression<Func<PresentationModelPerson, object>>> includes)
{
var applicationTake = take;
var applicationSkip = skip;
/*
* if I map this way the mapping on domain class will fail with the following error:
* System.InvalidOperationException: 'Code supposed to be unreachable'
* (there's a reason on my project to use this way)
*/
dynamic applicationOrderByObject = _mapper.Map(orderBy,
typeof(Expression<Func<IQueryable<PresentationModelPerson>, IOrderedQueryable<PresentationModelPerson>>>
),
typeof(Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>
>));
/*
// if I map this way, it works perfectly //
var applicationOrderBy =
_mapper
.MapExpression<
Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>>
>(orderBy);
*/
var applicationWhere = _mapper.MapExpression<Expression<Func<ApplicationModelPerson, bool>>>(where);
var applicationInclude =
_mapper.MapExpressionList<Expression<Func<ApplicationModelPerson, object>>>(includes).ToList();

var applicationPerson = new ApplicationPerson(_mapper);
applicationPerson.List(applicationTake, applicationSkip, applicationOrderByObject, applicationWhere,
applicationInclude);
throw new NotImplementedException();
}
}
public class ApplicationPerson
{
private readonly IMapper _mapper;
public ApplicationPerson(IMapper mapper) => _mapper = mapper;
public IEnumerable<ApplicationModelPerson> List(int take, int skip,
Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>> orderBy,
Expression<Func<ApplicationModelPerson, bool>> where, IList<Expression<Func<ApplicationModelPerson, object>>> includes)
{
var domainTake = take;
var domainSkip = skip;
// this mapping will fail whatever I use this way or _mapper.Map(object, sourceType, targetType) //
var domainOrderBy =
_mapper
.MapExpression<
Expression<Func<IQueryable<DomainModelPerson>, IOrderedQueryable<DomainModelPerson>>>
>(orderBy);
var domainWhere = _mapper.MapExpression<Expression<Func<DomainModelPerson, bool>>>(where);
var domainInclude =
_mapper.MapExpressionList<Expression<Func<DomainModelPerson, object>>>(includes).ToList();

var domainPerson = new DomainPerson(_mapper);
domainPerson.List(domainTake, domainSkip, domainOrderBy, domainWhere,
domainInclude);
throw new NotImplementedException();
}
}
public class DomainPerson
{
private readonly IMapper _mapper;
public DomainPerson(IMapper mapper) => _mapper = mapper;
public IEnumerable<DomainModelPerson> List(int take, int skip,
Expression<Func<IQueryable<DomainModelPerson>, IOrderedQueryable<DomainModelPerson>>> orderBy,
Expression<Func<DomainModelPerson, bool>> where, IList<Expression<Func<DomainModelPerson, object>>> includes)
{
throw new NotImplementedException();
}
}
public class ModelProfile : Profile
{
public ModelProfile()
{
CreateMap<PresentationModelPerson, ApplicationModelPerson>().ReverseMap();
CreateMap<ApplicationModelPerson, DomainModelPerson>().ReverseMap();
}
}
public class ExpressionProfile : Profile
{
public ExpressionProfile()
{
CreateMap<Expression<Func<PresentationModelPerson, bool>>,
Expression<Func<ApplicationModelPerson, bool>>>().ReverseMap();
CreateMap<Expression<Func<IQueryable<PresentationModelPerson>,
IOrderedQueryable<PresentationModelPerson>>>,
Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>>>().ReverseMap();
CreateMap<IList<Expression<Func<PresentationModelPerson, object>>>,
IList<Expression<Func<ApplicationModelPerson, object>>>>().ReverseMap();

CreateMap<Expression<Func<ApplicationModelPerson, bool>>,
Expression<Func<DomainModelPerson, bool>>>().ReverseMap();
CreateMap<Expression<Func<IQueryable<ApplicationModelPerson>,
IOrderedQueryable<ApplicationModelPerson>>>,
Expression<Func<IQueryable<DomainModelPerson>, IOrderedQueryable<DomainModelPerson>>>>().ReverseMap();
CreateMap<IList<Expression<Func<ApplicationModelPerson, object>>>,
IList<Expression<Func<DomainModelPerson, object>>>>().ReverseMap();
}
}
public class Container
{
public IMapper Mapper { get; }
public Container()
{
var mapperConfiguration = new MapperConfiguration(
configuration =>
{
configuration.AddExpressionMapping();
configuration.AddProfile<ModelProfile>();
configuration.AddProfile<ExpressionProfile>();
configuration.AllowNullCollections = true;
});
Mapper = mapperConfiguration.CreateMapper();
Mapper.ConfigurationProvider.AssertConfigurationIsValid();
}
}
internal class Program
{
private static void Main(string[] args)
{
var mapper = new Container().Mapper;
var presentationPerson = new PresentationPerson(mapper);
Expression<Func<IQueryable<PresentationModelPerson>, IOrderedQueryable<PresentationModelPerson>>> orderBy = persons =>
persons.OrderByDescending(person => person.Birthday);
Expression<Func<PresentationModelPerson, bool>> where = person => !string.IsNullOrEmpty(person.Name);
presentationPerson.List(1, 100, orderBy, where,
new List<Expression<Func<PresentationModelPerson, object>>>());
}
}
}

我在这里缺少什么吗?及时:.NET Core 2.2,AutoMapper 9.0,AutoMapper.Extensions.ExpressionMapping 3.0.1,仅此而已。

谢谢。

作者回答并确认这是一个错误,因此,我将在他们的Github页面上发布他们给我的解决方法。

这是问题的链接:https://github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping/issues/40

我们需要为它创建一个帮助程序,如下所示:

public static class ExpressionMappingHelper
{
public static LambdaExpression MapExpression(this IMapper mapper, LambdaExpression expression, Type sourceExpressionType, Type destExpressionType)
{
if (expression == null)
return default;
//This calls public static TDestDelegate MapExpression<TSourceDelegate, TDestDelegate>(this IMapper mapper, TSourceDelegate expression)
//in AutoMapper.Extensions.ExpressionMapping.MapperExtensions
return (LambdaExpression)"MapExpression".GetMapExpressionMethod().MakeGenericMethod
(
sourceExpressionType,
destExpressionType
).Invoke(null, new object[] { mapper, expression });
}
private static MethodInfo GetMapExpressionMethod(this string methodName)
=> typeof(AutoMapper.Extensions.ExpressionMapping.MapperExtensions).GetMethods().Single(m => m.Name == methodName && m.GetGenericArguments().Length == 2);
}

然后像这样调用扩展方法:

dynamic applicationOrderByObject = _mapper.MapExpression(orderBy,
typeof(Expression<Func<IQueryable<PresentationModelPerson>, IOrderedQueryable<PresentationModelPerson>>>
),
typeof(Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>
>));

这将是解决方法,直到自动映射器团队修复它。

希望这可以帮助某人,因为它帮助了我。

相关内容

最新更新