我有一个AutoMapper问题,这个问题让我疯狂了太长时间了。类似的问题也在AutoMapper用户网站上发布过,但并没有得到太多关注。
简要概述是我有一个容器类,它持有一个组件字典。这些组件是一个共同基类的派生对象。我还有一个平行结构,我正在使用它作为DTO对象进行映射。
生成的错误似乎表明映射器不能在我包含在CreateMap调用中的两个类之间进行映射。我认为错误与我拥有一个对象字典有关,这些对象不是容器层次结构的一部分。
我提前为下面的代码长度道歉。我的简单测试用例都能正常工作。不用说,只有更复杂的情况失败了。
以下是类:
感谢您的提前帮助。
Rick
简要概述是我有一个容器类,它持有一个组件字典。这些组件是一个共同基类的派生对象。我还有一个平行结构,我正在使用它作为DTO对象进行映射。
生成的错误似乎表明映射器不能在我包含在CreateMap调用中的两个类之间进行映射。我认为错误与我拥有一个对象字典有关,这些对象不是容器层次结构的一部分。
我提前为下面的代码长度道歉。我的简单测试用例都能正常工作。不用说,只有更复杂的情况失败了。
以下是类:
#region Dto objects
public class ComponentContainerDTO
{
public Dictionary<string, ComponentDTO> Components { get; set; }
public ComponentContainerDTO()
{
this.Components = new Dictionary<string, ComponentDTO>();
}
}
public class EntityDTO : ComponentContainerDTO
{
public int Id { get; set; }
}
public class ComponentDTO
{
public EntityDTO Owner { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string ComponentType { get; set; }
}
public class HealthDTO : ComponentDTO
{
public decimal CurrentHealth { get; set; }
}
public class PhysicalLocationDTO : ComponentDTO
{
public Point2D Location { get; set; }
}
#endregion
#region Domain objects
public class ComponentContainer
{
public Dictionary<string, Component> Components { get; set; }
public ComponentContainer()
{
this.Components = new Dictionary<string, Component>();
}
}
public class Entity : ComponentContainer
{
public int Id { get; set; }
}
public class Component
{
public Entity Owner { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string ComponentType { get; set; }
}
public class Health : Component
{
public decimal CurrentHealth { get; set; }
}
public struct Point2D
{
public decimal X;
public decimal Y;
public Point2D(decimal x, decimal y)
{
X = x;
Y = y;
}
}
public class PhysicalLocation : Component
{
public Point2D Location { get; set; }
}
#endregion
代码:
var entity = new Entity() { Id = 1 };
var healthComponent = new Health() { CurrentHealth = 100, Owner = entity, Name = "Health", Id = 2 };
entity.Components.Add("1", healthComponent);
var locationComponent = new PhysicalLocation() { Location = new Point2D() { X = 1, Y = 2 }, Owner = entity, Name = "PhysicalLocation", Id = 3 };
entity.Components.Add("2", locationComponent);
Mapper.CreateMap<ComponentContainer, ComponentContainerDTO>()
.Include<Entity, EntityDTO>();
Mapper.CreateMap<Entity, EntityDTO>();
Mapper.CreateMap<Component, ComponentDTO>()
.Include<Health, HealthDTO>()
.Include<PhysicalLocation, PhysicalLocationDTO>();
Mapper.CreateMap<Component, ComponentDTO>();
Mapper.CreateMap<Health, HealthDTO>();
Mapper.CreateMap<PhysicalLocation, PhysicalLocationDTO>();
Mapper.AssertConfigurationIsValid();
var targetEntity = Mapper.Map<Entity, EntityDTO>(entity);
当我调用Map()时出现的错误(简写堆栈跟踪):
AutoMapper.AutoMapperMappingException was unhandled
Message=Trying to map MapperTest1.Entity to MapperTest1.EntityDTO.
Using mapping configuration for MapperTest1.Entity to MapperTest1.EntityDTO
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
.
.
.
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[MapperTest1.Component, ElasticTest1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] to System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[MapperTest1.ComponentDTO, ElasticTest1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Using mapping configuration for MapperTest1.Entity to MapperTest1.EntityDTO
Destination property: Components
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.MapPropertyValue(ResolutionContext context, IMappingEngineRunner mapper, Object mappedObject, PropertyMap propertyMap)
.
.
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[MapperTest1.Component, ElasticTest1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] to System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[MapperTest1.ComponentDTO, ElasticTest1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Using mapping configuration for MapperTest1.Entity to MapperTest1.EntityDTO
Destination property: Components
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
.
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map MapperTest1.Component to MapperTest1.ComponentDTO.
Using mapping configuration for MapperTest1.Health to MapperTest1.HealthDTO
Destination property: Components
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
.
.
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map System.Decimal to System.Decimal.
Using mapping configuration for MapperTest1.Health to MapperTest1.HealthDTO
Destination property: CurrentHealth
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.MapPropertyValue(ResolutionContext context, IMappingEngineRunner mapper, Object mappedObject, PropertyMap propertyMap)
.
.
InnerException: System.InvalidCastException
Message=Unable to cast object of type 'MapperTest1.ComponentDTO' to type 'MapperTest1.HealthDTO'.
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at SetCurrentHealth(Object , Object )
.
.
感谢您的提前帮助。
Rick