Background: I want to hook in business rules at the point that DTOs are being mapped to entities. I figured encapsulating the mapping into an extension method would be a good route.
IEntityDto is the interface that all DTOs that can be directly mapped to entities implement.
The single instance works fine:
public static TEntity MapTo<TEntity>(this IEntityDto dto)
{
... Run Business Rules that don't require db access ...
return AutoMapper.Mapper.Map<TEntity>(dto);
}
I'd like to also extend ICollection the same way:
public static ICollection<TEntity> MapToCollection<TEntity>(this ICollection<IEntityDto> dtos)
{
... Run Business Rules that don't require db access ...
return AutoMapper.Mapper.Map<ICollection<TEntity>>(dtos);
}
Unfortunately, MapToCollection does not show up on the context menu or compile when applied to an ICollection of IEntityDto.
What am I missing to get this to work? Do I need to just extend ICollection where T is IEntityDto? I'd prefer to not have to include the DTO type when calling the extension method.
public static ICollection<TEntity>MapToCollection<TDto,TEntity>(this ICollection<TDto> dtos) where TDto: IEntityDto
{
... Do Work and Return ...
}
The above works, but I was hoping to infer T from the collection.
Thanks!
You effectively need a method with a signature of
public static ICollection<TEntity> MapToCollection<TEntity, TEntityDto>(
this ICollection<TEntityDto> dtos)
where TEntityDto : IEntityDto
... but that would force you to specify both type arguments, which I understand you don't want to do.
What you can do instead is go in two hops, e.g.
public static class DtoExtensions
{
public static CollectionMapper<TEntityDto> Map(this ICollection<TEntityDto> dtos)
where TEntityDto : IEntityDto
{
return new CollectionMapper<TEntityDto>(dtos);
}
}
public class CollectionMapper<TEntityDto> where TEntityDto : IEntityDto
{
private readonly ICollection<TEntityDto> dtos;
public CollectionMapper(ICollection<TEntityDto> dtos)
{
this.dtos = dtos;
}
public ICollection<TEntity> To<TEntity>()
{
// Business rules...
return AutoMapper.Mapper.Map<ICollection<TEntity>>(dtos);
}
}
You can now use:
var result = collection.Map().To<FooEntity>();
The Map
call infers TEntityDto
, and you specify TEntity
in the To
call.
See more on this question at Stackoverflow