It's not so much a question, as I have found a way to do what I want, but it seems like there should be a better way to do it. I've searched everywhere and not found anything.
Basically, I have what I consider a very standard object model.
public class Parent
{
private readonly IList<Child> _children = new List<Child>();
public IEnumerable<Child> Children { get { return _children; } }
public void AddChild(Child child)
{
child.Parent = this;
_children.Add(child);
}
}
and
public class Child
{
public Parent Parent { get; set; }
}
(I've omitted properties irrelevant to the problem and error checking and guarding for the sake of clarity...)
public class ParentDTO
{
List<ChildDTO> Children = new List<ChildDTO>();
}
and
public class ChildDTO
{
}
The reason I'm using a method to add children to the collection is to maintain control of business logic that needs to be processed when a child is added.
With the standard mapping of:
Mapper.CreateMap<Parent, ParentDTO>();
Mapper.CreateMap<ParentDTO, Parent>();
Mapper.CreateMap<Child, ChildDTO>();
Mapper.CreateMap<ChildDTO, Child>();
It seems to work fine coming from the service layer. The children of the domain object map perfectly to the list of ChildDTO
instances.
However, when mapping back the other way, the collection on the domain model isn't set - because it's readonly, obviously. There doesn't appear to be any way to directly set the private field using AutoMapper. I have tried various suggestions found on here, and other parts of the internet.
In the end, I came up with the following mapping:
Mapper.CreateMap<ParentDTO, Parent>()
.ForMember(m => m.Children, o => o.Ignore())
.AfterMap((s, d) =>
{
foreach(var c in s.Children)
d.AddChild(Mapper.Map<ChildDTO, Child>(c));
});
This works as I required. However, I can't help feeling that there has to be a better way, and I haven't tested this with an existing parent that's had children modified and maybe added and removed, so I know it's not actually correct yet. Ultimately, this domain model is persisted using NHibernate, so I do have to worry about that. But, one thing at a time. :)
Hopefully this might help someone else who's encountering the same problem, and maybe someone who's solved it properly will be able to correct me.