[英]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>>
>));
這將是解決方法,直到AutoMapper團隊對其進行修復。
希望這能對我有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.