AutoMapper does not work for the Container class

I have an AutoMapper problem that has made me crazy for too long. A similar question was also posted on the AutoMapper user site, but he did not get much love.

The summary is that I have a container class that contains a component dictionary. Components are a derived object of a common base class. I also have a parallel structure that I use as the DTO objects I want to map to.

The error that is generated seems to say that the mapping cannot display between the two classes that I included in the calls to CreateMap. I think the error is due to the fact that I have a dictionary of objects that are not part of the container hierarchy.

I apologize in advance for the length of the code below. My simple test cases work. Needless to say, his only more complicated case is that he fails.

Here are the classes:

#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

The code:

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);

Error when calling Map () (trimming the short paragraph):

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 )
.
.

Thanks in advance.

Rick

+3
source share
1 answer

This turned out to be a bug fixed in version 1.1.0.184.

Thanks to Jimmy for fixing it.

Rick

+3
source

Source: https://habr.com/ru/post/1742035/


All Articles