Home > C#, Tips > [EN] AutoMapper is trying to be too smart ?

[EN] AutoMapper is trying to be too smart ?

February 19, 2011 Leave a comment Go to comments

Sometimes we need to copy a set of properties from one class to another. The easiest way is to copy each property by hand, but making this by hand for 10 or 20 properties is a booring job, and for a bigger set of classes this makes the developer work monotonous and consumes a lot of time. One of the solution to avoid this hand copying for example from DTO to POCO objects is to use the AutoMapper in our project.

I discovered the AutoMapper one day, while I was browsing Goyello’s blogs and I found this post. It really helped me to do my work easier, but really, was the first time easy ?

Let’s look at two class definitions:

    public class MyClassA
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    public class MyClassB
    {
        public int ID { get; set; }

        public int TEST_ID { get; set; }

        public string Name { get; set; }

        public string Surname { get; set; }
    }

As we see, they do not inherit from any other base interface or class. They have only two the same properties: ID and Name. Now we want, that all fields from an instance of MyClassA will be mapped to an instance to MyClassB (all fields with the same name). An example of the instances is presented below:

MyClassA myA = new MyClassA { ID = 1, Name = "MyA" };
MyClassB myB = new MyClassB { ID = 2, TEST_ID = 8, Name = "MyB", Surname = "Surrender" };

Now we want, that after mapping myA to myB, the myB instance will contain such values

  ID = 1
  TEST_ID = 8
  Name = MyA
  Surname = Surrended

so only the ID na Name should change. But, is it true? Let’s try, and see:
As we can see the TEST_ID changed too, and this was not intended. But is it a bug? or feature :) To look at this, I downloaded the sources, and debugged step by step and looked what automapper is creating, in result I found this feature.

string[] matches = mappingOptions.DestinationMemberNamingConvention.SplittingExpression
  .Matches(nameToSearch)
  .Cast<Match>()
  .Select(m => m.Value)
  .ToArray();

Let’s take a look at the DestinationMemberNamingConvertion property. By default this is an instance of PascalCaseNamingConvention class, which SplittinExpression is a regular expression :

(\p{Lu}+(?=$|\p{Lu}[\p{Ll}0-9])|\p{Lu}?[\p{Ll}0-9]+)

The NameToSearch contains in one step of our examplese the name of TEST_ID, and in result there is one match (as You can see, when you have a RegExp compiler in head).

And in result the TEST_ID from MyClassB will be mapped to ID property of MyClassA.

How to ommit this ‘inconvenience‘ ?

1. In our example, when we change the TEST_ID to Test_ID, the field won’t be mapped.

2. While creating map, You can select, which field(s) to ommit

Mapper.CreateMap<MyClassA, MyClassB>().ForMember(x => x.TEST_ID, opt => opt.Ignore());

3. You can force the Automapper not to use this smart feature, by creating Your custom NamingConvention class

public class MyConvention : INamingConvention
{
  private static readonly Regex _regex = new Regex(" ");

  public Regex SplittingExpression
  {
    get { return _regex; }
  }

  public string SeparatorCharacter
  {
    get { return String.Empty; }
  }
}

and then when initializing the automapper, You have only to tell the automapper, what kind of Naming Convention should it use

Mapper.Initialize(x =>
{
  x.DestinationMemberNamingConvention = new MyConvention();
});

And that’s all. Of course changing the behaviour of automapper, can change the mapping somewhere in our code, so You should be aware of this.

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: