Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper and Generic Mapping

Tags:

automapper

Is there anyway to condense this down with automapper? It is just getting to big.

        Mapper.CreateMap<PagedResult<Headline>, PagedResult<HeadlineModel>>();
        Mapper.CreateMap<PagedResult<Event>, PagedResult<EventModel>>();
        Mapper.CreateMap<PagedResult<GymCourt>, PagedResult<GymCourtModel>>();
        Mapper.CreateMap<PagedResult<Gym>, PagedResult<GymModel>>();
        Mapper.CreateMap<PagedResult<EventGymCourt>, PagedResult<EventGymCourtModel>>();
        Mapper.CreateMap<PagedResult<Division>, PagedResult<DivisionModel>>();
        Mapper.CreateMap<PagedResult<Team>, PagedResult<TeamModel>>();
        Mapper.CreateMap<PagedResult<DivisionTeam>, PagedResult<DivisionTeamModel>>();
        Mapper.CreateMap<PagedResult<MemberTeam>, PagedResult<MemberTeamModel>>();
        Mapper.CreateMap<PagedResult<TeamCoach>, PagedResult<TeamCoachModel>>();
        Mapper.CreateMap<PagedResult<DivisionAsset>, PagedResult<DivisionAssetModel>>();
        Mapper.CreateMap<PagedResult<EventAsset>, PagedResult<EventAssetModel>>();
        Mapper.CreateMap<PagedResult<Event>, PagedResult<ApiEvent>>();
        Mapper.CreateMap<PagedResult<Price>, PagedResult<PriceModel>>();
        Mapper.CreateMap<PagedResult<DivisionPrice>, PagedResult<DivisionPriceModel>>();
        Mapper.CreateMap<PagedResult<EventPrice>, PagedResult<EventPriceModel>>();
        Mapper.CreateMap<PagedResult<Division>, PagedResult<ApiDivision>>();
        Mapper.CreateMap<PagedResult<Data.Entities.Player>, PagedResult<PlayerModel>>();
like image 620
Mike Flynn Avatar asked Dec 12 '22 06:12

Mike Flynn


2 Answers

What you can do is to use an extension method. If you add this class:

public static class MappingExtensions
{
    public static IMappingExpression<TSrc, TDest> IncludePagedResultMapping<TSrc, TDest>(this IMappingExpression<TSrc, TDest> expression)
    {
        Mapper.CreateMap<PagedResult<TSrc>, PagedResult<TDest>>()
            .ForMember(dest => dest.HasMoreResults, opt => opt.MapFrom(src => src.HasMoreResults))
            .ForMember(dest => dest.NextPage, opt => opt.MapFrom(src => src.NextPage));

        return expression;
    }
}

then you can include the paged mappings as part of your entity to model mappings, viz:

Mapper.CreateMap<Headline, HeadlineModel>().IncludePagedResultMapping();
Mapper.CreateMap<Event, EventModel>().IncludePagedResultMapping();
Mapper.CreateMap<GymCourt, GymCourtModel>().IncludePagedResultMapping();
Mapper.CreateMap<Player, PlayerModel>().IncludePagedResultMapping();
like image 198
Rob Lyndon Avatar answered Feb 27 '23 12:02

Rob Lyndon


As far as I know there is no build in support in Automapper for custom mapper registration conventions, but you can DRY it up a little with some reflection:

var mappingDictionary = new Dictionary<Type, Type>
{
    {typeof (Headline), typeof (HeadlineModel)},
    {typeof (Event), typeof (EventModel)},
    //...
};
foreach (var sourceType in mappingDictionary.Keys)
{
    Mapper.CreateMap(
       typeof (PagedResult<>).MakeGenericType(sourceType),
       typeof (PagedResult<>).MakeGenericType(mappingDictionary[sourceType]));
}

Or if you always follow your convention Headline -> HeadlineModel etc. With some more reflection you don't need to build up the mapping by hand:

var modelAssembly = Assembly.GetAssembly(typeof(HeadlineModel));
var otherAssembly = Assembly.GetAssembly(typeof(Headline));
foreach (var destinationType in modelAssembly.GetTypes()
    .Where(t => t.Namespace == "ModelNaspace" && t.Name.EndsWith("Model")))
{
    var destinationName = destinationType.Name.Replace("Model", "");
    var sourceType = otherAssembly.GetTypes()
        .SingleOrDefault(t => t.Namespace == "OtherNamespace" && t.Name == destinationName);

    if (sourceType == null)
    {
        //log warning
        continue;
    }

    Mapper.CreateMap(
       typeof (PagedResult<>).MakeGenericType(sourceType),
       typeof (PagedResult<>).MakeGenericType(destinationType));
}
like image 44
nemesv Avatar answered Feb 27 '23 12:02

nemesv