Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper ignoring ignore for properties

Tags:

automapper

I would like to ignore certain properties when mapping deep (ie levels > 1) object models.

The following test works fine:

class Foo
{
    public string Text { get; set; }
}

class Bar
{
    public string Text { get; set; }
}

Mapper.CreateMap<Foo, Bar>()
      .ForMember(x => x.Text, opts => opts.Ignore());

var foo = new Foo { Text = "foo" };
var bar = new Bar { Text = "bar" };
Mapper.Map(foo, bar);
Assert.AreEqual("bar", bar.Text);

However when I try to do the same mapping but have Foo and Bar as properties on a parent class the following test fails:

class ParentFoo
{
    public Foo Child { get; set; }
}

class ParentBar
{
    public Bar Child { get; set; }
}

Mapper.CreateMap<ParentFoo, ParentBar>();

Mapper.CreateMap<Foo, Bar>()
      .ForMember(x => x.Text, opts => opts.Ignore());

var parentFoo = new ParentFoo          
{
    Child = new Foo { Text = "foo" }
};

var parentBar = new ParentBar
{
    Child = new Bar { Text = "bar" }
};

Mapper.Map(parentFoo, parentBar);
Assert.AreEqual("bar", parentBar.Child.Text);

Instead of ignoring the text of the Child class (ie left it as "bar") automapper sets the value to null. What am I doing wrong with my mapping configuration?

like image 561
Brownie Avatar asked Mar 23 '11 06:03

Brownie


1 Answers

There are two ways Automapper can perform the mapping. The first way is to simply give Automapper your source object and it will create a new destination object and populate everything for you. This is the way most apps use Automapper. However, the second way is to give it both a source and an existing destination and Automapper will update the existing destination with your mappings.

In the first example, you're giving it an existing destination value so Automapper will use that. In the second example, Automapper is going to do the mapping for ParentFoo and ParentBar, but when it gets to the Child, it's going to create a new Child and then do the mapping (this is the default behavior). This results in the Text property being null. If you want to use the existing Child object, you'll need to configure Automapper to do that with UseDestinationValue:

Mapper.CreateMap<ParentFoo, ParentBar>()
    .ForMember(b => b.Child, o => o.UseDestinationValue());

This makes your test pass (as long as you get rid of the first space when setting the parentBar.Child.Text!).

like image 65
PatrickSteele Avatar answered Oct 21 '22 17:10

PatrickSteele