Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper mapping property unexpectedly by partial property name match

Tags:

c#

automapper

I have two classes being mapped. The source class has a DateTime property that gets mapped to a destination property of type long (DateTime.Ticks), they are UpdateDt and UpdateDtTicks respectively.

When I use Automapper to map these two classes my UpdateDtTicks property automaticly gets the value from the UpdateDt property, even though the property names are not the same and I have not explicitly set the mapping for this property.

Is Automapper setting the property automatically because the property names only differ at the end? If not why is this happening as it is unexpected behavior.

Please see the code below:

static void Main(string[] args)
{
    Configuration.Configure();

    var person = new OrderDto 
    {
        OrderId  = 999,
        MyDate   = new DateTime(2015, 1, 1, 4, 5, 6)
    };

    var orderModel = Mapper.Map<OrderModel>(person); 

    Console.WriteLine(new DateTime(orderModel.MyDateTicks.Value));
    Console.ReadLine();           
}

public class OrderDto 
{
    public int      OrderId  { get; set; }
    public DateTime MyDate   { get; set; }
}

public class OrderModel 
{
    public int      OrderId     { get; set; }
    public long?    MyDateTicks { get; set; }
}

public class Configuration
{
    public static void Configure() 
    {
        Mapper.CreateMap<OrderDto, OrderModel>();                   
    }
} 

The result in the console:

enter image description here

And a watch:

enter image description here

like image 467
Tjaart van der Walt Avatar asked Sep 07 '15 11:09

Tjaart van der Walt


1 Answers

You are triggering AutoMapper's flattening feature. Frome the documentation:

When you configure a source/destination type pair in AutoMapper, the configurator attempts to match properties and methods on the source type to properties on the destination type. If for any property on the destination type a property, method, or a method prefixed with "Get" does not exist on the source type, AutoMapper splits the destination member name into individual words (by PascalCase conventions).

Thus, given the following example (from their docs as well, shortened in my answer):

public class Order
{
    public Customer Customer { get; set; }
}

public class Customer
{
    public string Name { get; set; }
}

public class OrderDto
{
    public string CustomerName { get; set; }
    public decimal Total { get; set; }
}

Mapper.CreateMap<Order, OrderDto>();

var order = new Order
{
    Customer = new Customer
    {
        Name = "John Doe"
    }
};

OrderDto dto = Mapper.Map<Order, OrderDto>(order);

The CustomerName property matched to the Customer.Name property on Order.

This is exactly the same as MyDateTicks matching MyDate.Ticks, which returns a long as necessary...

like image 166
MarioDS Avatar answered Oct 19 '22 07:10

MarioDS