Исключение сопоставления Automapper несмотря на успех AssertConfigurationIsValid()

Я действительно почесал голову от этого. Я обновил с Automapper 2.2.1 до 3.1.1 и код, который работал, прежде чем сломался. Я пытаюсь получить больше диагностической информации для устранения проблемы.

В модульном тесте я получаю проход, так как ошибок нет

[TestClass]
public class TestOldWcfEndpoint
{
    public TestContext TestContext { get; set; }

    bool FieldWasSpecified;

    [TestInitialize]
    public void TestInitialize()
    {
        AutoMapperUnity.RegistrationInUnitTesting();
        this.FieldWasSpecified = true;
    }

    [TestMethod]
    public void Test_OldWcfHosting_AutomapperConfigurationIsValid()
    {
        try
        {
            AutoMapper.Mapper.AssertConfigurationIsValid();
        }
        catch (AutoMapper.AutoMapperMappingException aex)
        {
            this.TestContext.WriteLine(aex.Message);
            throw;
        }
    }
}

AutoMapperUnity - это статический вспомогательный класс для подключения к контейнеру Unity:

public static class AutoMapperUnity
{
    private static void Regsitrations()
    {
        Mapper.Reset();
        var business = new BusinessLogicMaps(); business.Configure();
        var api = new ApiServiceMaps(); api.Configure();
        var wcf = new OldWcfMaps(); wcf.Configure();
        Mapper.Configuration.AllowNullCollections = true;
    }

    public static void Registration(IUnityContainer container)
    {
        Regsitrations();
        container.RegisterType<IMappingEngine>(new InjectionFactory(_ => Mapper.Engine));
        container.RegisterType<IConfiguration>(new InjectionFactory(_ => Mapper.Configuration));
        container.RegisterType<IConfigurationProvider>(new InjectionFactory(_ => Mapper.Configuration));
    }
}

Проблема возникает с картами wcf. Конечная точка Wcf основана на тех же контрактах DTO, которые используются клиентами Web Api. Контракты Wcf точно такие же, за исключением аннотаций данных.

public class OldWcfMaps
{
    void CreateMapForCodes()
    {
        Mapper.CreateMap<CodeTypeDTO, CodeTypeWcfDTO>()
            .ForMember(s => s.IDSpecified, o => o.Ignore());
        Mapper.CreateMap<CodeTypeWcfDTO, CodeTypeDTO>();

        Mapper.CreateMap<CodeDTO, CodeWcfDTO>()
            .ForMember(s => s.ActiveSpecified, o => o.Ignore())
            .ForMember(s => s.CodeTypeIDSpecified, o => o.Ignore())
            .ForMember(s => s.IDSpecified, o => o.Ignore());
        Mapper.CreateMap<CodeWcfDTO, CodeDTO>();
    }

    void CreateMapForCodeReports()
    {
        Mapper.CreateMap<CodeReportDTO, CodeReportWcfDTO>()
            .ForMember(s => s.ActiveSpecified, o => o.Ignore())
            .ForMember(s => s.AppIDSpecified, o => o.Ignore())
            .ForMember(s => s.IDSpecified, o => o.Ignore())
            .ForMember(s => s.CodeIDSpecified, o => o.Ignore())
        Mapper.CreateMap<CodeReportWcfDTO, CodeReportDTO>();
    }

    void CreateMapForShiftReports()
    {
        this.CreateMapForCodeReports();

        Mapper.CreateMap<ShiftReportDTO, ShiftReportWcfDTO>()
            .ForMember(s => s.NumberOfReportsSpecified, o => o.Ignore());
        Mapper.CreateMap<ShiftReportWcfDTO, ShiftReportDTO>();
    }

    public void Configure()        
    {
        this.CreateMapForCodes();
        this.CreateMapForShiftReports();
    }
}

}

[ServiceBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class TimeClockServices : ITimeClockServices
{
    /// <summary>
    /// Reference to the AutoMapper Engine.
    /// </summary>
    private readonly IMappingEngine MapperEngine;
    private readonly ILogFactory LogFactory;
    private readonly ITimeClockDataService TimeClockApi;

    public TimeClockServices(IMappingEngine mapper, ITimeClockDataService timeClockServices, ILogFactory logger)
    {
        this.MapperEngine = mapper;
        this.TimeClockApi = timeClockServices;
        this.LogFactory = logger;
    }

    public IEnumerable<CodeReportWcfDTO> GetCodeReports(ApplicationsEnum AppID, short DepartmentID, long CaseID, bool Active)
    {
        IEnumerable<CodeReportWcfDTO> groupOfWcfCodeReportDTOs = null;
        try
        {
            // Get Data using shared internal interface.
            IEnumerable<CodeReportDTO> codeReportDTOs =
                this.TimeClockApi.GetCodeReports(AppID, DepartmentID, CaseID, Active);

            // Convert the Data to the Wcf Extension Class.
            // **OFFENDING LINE**
            codeReportWcfDTOs =
                this.MapperEngine.Map<IEnumerable<CodeReportDTO>, IEnumerable<CodeReportWcfDTO>>(codeReportDTOs);

        }
        catch (BLException bex)
        {
            throw new FaultException<BLExceptionFault>(
                new BLExceptionFault("Business Engine Exception was thrown.", bex));
        }

        return codeReportWcfDTOs;
    }
}

В конечном итоге это приводит к ошибке:

Missing type map configuration or unsupported mapping.

Mapping types:
CodeReportDTO -> CodeReportWcfDTO
Api.Contract.Entities.CodeReportDTO -> Legacy.Contracts.WcfDTO.CodeReportWcfDTO

Destination path:
IEnumerable`1[0]

Source value:
Api.Contract.Entities.CodeReportDTO

С учетом всего вышесказанного я не знаю, на что он на самом деле не справляется, чтобы лучше устранять неполадки. Уровень DTO также сопоставляется с эквивалентами бизнес-объектов.

1 ответ

Решение

Я пропустил что-то очень важное. Когда я разрешил специфичные для Wcf DTO, он получал их из проекта Unit Test, который является прокси-клиентом, а не проектом хост-сервера.

Эта ошибка является правильной, потому что Proxy.CodeTypeWcfDTO!= OldWcf.CodeTypeWcfDTO.

Если вы столкнулись с этой проблемой, убедитесь, что вы проверяете правильность контрактов.

Другие вопросы по тегам