13

I have classes to map, but they don't have default constructors, and I don't want them to have. This is because I only map to/from already existing objects.

public class Order
{
    public string OrderName { get; set; }
    public Order(string name) 
    { 
        this.OrderName = name; 
    }
}

public class OrderProcessor
{
    private IService service;
    public string OrderName { get; set; }

    public OrderProcessor(IService service)
    { 
        this.service = service; 
        Mapper.Initialize(config => config.CreateMap<Order, OrderProcessor>());
    }

    public void Init()
    { 
        var order = this.service.GetOrder();

        // this works
        Mapper.Map(order, this);

        // this fails
        Mapper.Configuration.AssertConfigurationIsValid();
    }
}

AutoMapper.AutoMapperConfigurationException : Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters

Order -> OrderProcessor (Destination member list)

No available constructor.

at Test() in Tests.cs:line

How to make configuration assert pass and why it fails when I don't want to create new objects?

one_mile_run
  • 3,264
  • 4
  • 26
  • 29

2 Answers2

28

I also stumbled onto this problem after recently upgrading from Automapper 4.x to 6.x.

You need to tell AutoMapper that you don't intend to have it construct the destination type by calling CreateMap<TSource, TDest>().DisableCtorValidation().

As per the method documentation:

    // Summary:
    //     Disable constructor validation. During mapping this map is used 
    //     against an existing destination object and never constructed itself.
    //
Andre Luus
  • 3,692
  • 3
  • 33
  • 46
  • Bingo, this is exactly what I've searched for. Tested and works. Thank you. – one_mile_run Jul 05 '17 at 13:09
  • How do I add this for Map(object source, Action opts) implementation? I am really new to this – Ybhaw Jun 06 '19 at 01:03
  • 1
    @VaibhawKumar, it should affect all uses of the map. `CreateMap` defines the mapping between two types. The `Map` method you show above will still be doing a conversion between the actual runtime type of the source object to the `TDestination` type. It has been a while since I've worked on this, but I think you can also say `mappingConfig.ForAll(map => map.DisableCtorValidation())` - but this is just pseudo-ish code. You'll have to elaborate or me to be more specific. – Andre Luus Jun 06 '19 at 11:31
3

You need to use .ConstructUsing(), as your type does not have a parameter-less constructor...

So something like;

 Mapper.Initialize(config => 
    config.CreateMap<Order, OrderProcessor>()
    .ConstructUsing(x => new OrderProcessor(new WhateverService()));
);

You may obviously need to resolve WhateverService using whatever DI Framework you are using....

Milney
  • 6,253
  • 2
  • 19
  • 33
  • My OrderProcessor in reality has couple more dependencies. Resolving them manually during mapping is not a way to go. Also, in reality OrderProcessor is a ViewModel, which cannot be recreated (for sample I used simplistic version). – one_mile_run Apr 25 '17 at 09:45
  • What do you mean it 'cannot be recreated'? Sadly you will have to either do this, or not use Automapper... – Milney Apr 25 '17 at 09:46
  • Only alternative is writing your own Mapping Extension, which uses the DI Framework... but this will actually be more work and overkill in your situation. If you want to try that here is documentation from automapper which explains it: https://github.com/AutoMapper/AutoMapper/wiki/Dependency-injection – Milney Apr 25 '17 at 09:47
  • So I have an OrderViewModel that has binding properties. I wanted to map them from OrderModel when some ICommand is executed in OrderViewModel. So I assume I shouldn't recreate OrderViewModel, when it is already binded to View and being displayed. – one_mile_run Apr 25 '17 at 09:49
  • I have no idea what you mean... That does not make sense – Milney Apr 25 '17 at 09:50