Reputation: 22064
I have a collection of EntityDtos.
Each EntityDto has a property called EntityType.
Each of these EntityTypes correspond to a different subclass, something like this
abstract class EntityBase { EntityType = EntityType.Base; }
class EntityOne : EntityBase { EntityType = EntityType.One; }
class EntityTwo : EntityBase { EntityType = EntityType.Two; }
I am trying to map to a collection of EntityBase. AutoMapper fails with the error "Instances of abstract classes cannot be created". I have the Type enum, and thus know what type each should be mapped to...but really, just want them all mapped into my EntityBase collection.
I can't figure this out...
I have this working, but it's VERY ugly.
Mapper.CreateMap<EntityCollectionDto, EntityCollection>().ForMember(
s => s.Entities, d => d.MapFrom(
x => new List<EntityBase>(
from p in x.Entitys
select p.EntityType == EntityType.One ? Mapper.Map<EntityOne>(p) as EntityBase
: p.EntityType == EntityType.Two ? Mapper.Map<EntityTwo>(p) as EntityBase
: Mapper.Map<EntityThree>(p) as EntityBase
)
)
);
Mapper.CreateMap<EntityDto, EntityOne>();
Mapper.CreateMap<EntityDto, EntityTwo>();
Upvotes: 1
Views: 3364
Reputation: 5144
I don't know if you'll like this any better, but assuming the entity classes as follows:
public abstract class EntityBase
{
public EntityType EntityType { get { return EntityType.Base; } }
}
public class EntityOne : EntityBase
{
public new EntityType EntityType { get { return EntityType.One; } }
}
public class EntityTwo : EntityBase
{
public new EntityType EntityType { get { return EntityType.Two; } }
}
public class EntityThree : EntityBase
{
public new EntityType EntityType { get { return EntityType.Three; } }
}
public class EntityCollection
{
public IList<EntityBase> Entities { get; set; }
}
public class EntityDto
{
public EntityType EntityType { get; set; }
}
public class EntityCollectionDto
{
public IList<EntityDto> Entities { get; set; }
}
You can create a TypeConverter
:
public class EntityTypeConverter : AutoMapper.TypeConverter<EntityDto, EntityBase>
{
protected override EntityBase ConvertCore(EntityDto source)
{
switch (source.EntityType)
{
case EntityType.One:
return AutoMapper.Mapper.Map<EntityOne>(source);
case EntityType.Two:
return AutoMapper.Mapper.Map<EntityTwo>(source);
default:
return AutoMapper.Mapper.Map<EntityThree>(source);
}
}
}
This will then simplify your mapping to:
AutoMapper.Mapper.CreateMap<EntityDto, EntityBase>()
.ConvertUsing(new EntityTypeConverter());
AutoMapper.Mapper.CreateMap<EntityDto, EntityOne>();
AutoMapper.Mapper.CreateMap<EntityDto, EntityTwo>();
AutoMapper.Mapper.CreateMap<EntityDto, EntityThree>();
AutoMapper.Mapper.CreateMap<EntityCollectionDto, EntityCollection>();
AutoMapper.Mapper.AssertConfigurationIsValid();
So you still have the specific mapping in the TypeConverter
(I'm not sure there's a way to avoid that), but I think the end result is a bit cleaner.
Upvotes: 2