1

I am using Automapper to map my domain model (nHibernate) to my view models and back. Everything is pretty smooth.

Now I need to map an entity (domain entity) to itself cause I want to define some business rules there.

I need to define different mappings for the same type more than once. I already use profiles for each type of mapping:

public static void Configure()
{
    Mapper.Initialize(a =>
    {
        Mapper.AddProfile(new OrderViewModelMapperProfile());
        Mapper.AddProfile(new OrderToOrder1MapperProfile());
        Mapper.AddProfile(new OrderToOrder2MapperProfile());
    });
}

And this is my profile (simplified):

public class OrderToOrder1MapperProfile : Profile
{
     protected override void Configure()
     {
         this.CreateMap<Domain.Order, Domain.Order>()
              .WithProfile("Profile001")
              .ForMember(dest => dest.Code, opt => opt.MapFrom(source => System.Guid.Empty))
              .ForMember(dest => dest.OrderLines, opt => opt.Ignore())
              .AfterMap((source, destination) =>
              {
                  foreach (var line in source.OrderLines)
                  {
                      destination.AddOrderLine(Mapper.Map<Domain.OrderLine, Domain.OrderLine>(line));
                  }

              });

         this.CreateMap<Domain.OrderLine, Domain.OrderLine>()
             .ForMember(dest => dest.Order, opt => opt.Ignore())
             .ForMember(dest => dest.Code, opt => opt.MapFrom(source => System.Guid.Empty));
        }
}

As you can see I need to do a few things in AfterMap.

My second profile OrderToOrder2MapperProfile looks similar to the one show here so I won't paste the code.

When I map my object:

Domain.Order order = new Domain.Order();
var order2 = Mapper.Map<Domain.Order, Domain.Order>(order);

both profiles are processed.

I decided to follow the path suggested on SO and I've created my "custom" engine:

private IMappingEngine CustomMappingEngine()
{
    ConfigurationStore store = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);
    MappingEngine engine = new MappingEngine(store);
    store.AddProfile(new OrderToOrder2MapperProfile());
    store.AllowNullDestinationValues = true;
    store.AssertConfigurationIsValid();
    return (engine);
}

Now everything works fine except for the mapping of the lines; both pipes are processed even if I am using the custom engine to map my object:

Domain.Order order = new Domain.Order();
var newEngine = CustomMappingEngine();
var order2 = newEngine.Map<Domain.Order, Domain.Order>(order);

I guess the problem sits in the fact that I am using the singleton Mapper (engine) here:

destination.AddOrderLine(Mapper.Map<Domain.OrderLine, Domain.OrderLine>(line))

I've tried to find a way to using the current engine inside a profiler but I don't seem to be able to get it in any way.

The only possible solution is to pass the engine in the constructor of my profiler:

public class OrderToOrder2MapperProfile : Profile
{
    private readonly IMappingEngine CurrentMappingEngine = null;

    public OrderToOrder2MapperProfile(IMappingEngine mappingEngine)
    {
        this.CurrentMappingEngine = mappingEngine;
    }

    protected override void Configure()
    {
        this.CreateMap<Domain.Order, Domain.Order>()
            .WithProfile("Profile002")
            .ForMember(dest => dest.Code, opt => opt.MapFrom(source => System.Guid.Empty))
            .ForMember(dest => dest.OrderLines, opt => opt.Ignore())
            .AfterMap((source, destination) =>
            {
                foreach (var line in source.OrderLines)
                {
                destination.AddOrderLine(this.CurrentMappingEngine.Map<Domain.OrderLine, Domain.OrderLine>(line));
                }

             });

             this.CreateMap<Domain.OrderLine, Domain.OrderLine>()
                 .ForMember(dest => dest.Order, opt => opt.Ignore())
                 .ForMember(dest => dest.Code, opt => opt.MapFrom(source => System.Guid.Empty));
            }
}

And use the current engine here:

destination.AddOrderLine(this.CurrentMappingEngine.Map<Domain.OrderLine, Domain.OrderLine>(line));

QUESTION:

Is this the only possible solution or there are better alternatives?
Am I doing things the proper way?

If someone is interested I've created a github repository which uses StructureMap as a test case.

Community
  • 1
  • 1
LeftyX
  • 35,328
  • 21
  • 132
  • 193

0 Answers0