我真的在这方面摸不着头脑。我已经从 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 层也被映射到业务对象等价物。