簡體   English   中英

System.InvalidOperationException:'代碼應該無法訪問'

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM