尽管AssertConfigurationIsValid()成功,但Automapper Mapping异常

时间:2014-03-27 22:04:57

标签: c# wcf automapper-3

我真的很抓头。我已经从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端点建立在Web Api客户端使用的相同DTO合同之上。除数据注释外,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层也会映射到Business Object的等价物。

1 个答案:

答案 0 :(得分:0)

我错过了非常重要的事情。当我解决了Wcf特定的DTO时,它是从单元测试项目获得的,它是代理客户端而不是服务器主机项目。

此错误是正确的,因为Proxy.CodeTypeWcfDTO!= OldWcf.CodeTypeWcfDTO。

如果您遇到此问题,请务必检查您正在查看合同的纳税空间!