[英]System.InvalidOperationException: 'Code supposed to be unreachable'
after some discussion with AutoMapper team, they recommended me to put my question here. 与AutoMapper团队讨论后,他们建议我在这里提出问题。
In short, if I map the expressions that I need using 简而言之,如果我映射需要使用的表达式
MapExpression<T>(source)
it works perfectly fine (considering using the AutoMapper.Extensions.ExpressionMapping framework). 它工作得很好(考虑使用AutoMapper.Extensions.ExpressionMapping框架)。
BTW, the authors said me that, even if I try to map using 顺便说一句,即使我尝试使用
Map(object, sourceType, targetType)
it should work normally but, when I use this method, I have the error as described in the title of this post. 它应该可以正常工作,但是当我使用此方法时,出现了本文标题中所述的错误。
To help, I wrote a full example on how to reproduce the problem as it follows bellow: 为了提供帮助,我写了一个完整的示例,说明如何重现以下问题:
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>>>());
}
}
}
Is there anything that I'm missing here? 我在这里想念什么吗? In time: .NET Core 2.2, AutoMapper 9.0, AutoMapper.Extensions.ExpressionMapping 3.0.1 and nothing else. 及时发布:.NET Core 2.2,AutoMapper 9.0,AutoMapper.Extensions.ExpressionMapping 3.0.1,仅此而已。
Thank you. 谢谢。
Author answered and confirmed that it's a bug so, I'm posting the workaround they gave me on their Github page. 作者回答并确认这是一个错误,因此,我在他们的Github页面上发布了他们给我的解决方法。
Here's the link for the issue: https://github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping/issues/40 这是问题的链接: https : //github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping/issues/40
We need to create a helper for it, like this: 我们需要为此创建一个助手,如下所示:
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);
}
Then call the extension method like this: 然后像这样调用扩展方法:
dynamic applicationOrderByObject = _mapper.MapExpression(orderBy,
typeof(Expression<Func<IQueryable<PresentationModelPerson>, IOrderedQueryable<PresentationModelPerson>>>
),
typeof(Expression<Func<IQueryable<ApplicationModelPerson>, IOrderedQueryable<ApplicationModelPerson>>
>));
This will be the workaround until the AutoMapper team fixes it. 这将是解决方法,直到AutoMapper团队对其进行修复。
Hope that this can help someone as it helped me. 希望这能对我有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.