使用AutoMapper映射只读子集合

Geo*_*ett 16 collections automapper

这不是一个问题,因为我找到了一种方法来做我想做的事情,但似乎应该有更好的方法来做到这一点.我到处搜索,没找到任何东西.

基本上,我有我认为非常标准的对象模型.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

public class Child
{
    public Parent Parent { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

(为了清楚起见,我省略了与问题无关的属性以及错误检查和保护......)

public class ParentDTO
{
    List<ChildDTO> Children = new List<ChildDTO>();
}
Run Code Online (Sandbox Code Playgroud)

public class ChildDTO
{
}
Run Code Online (Sandbox Code Playgroud)

我使用方法将子项添加到集合的原因是为了保持对添加子项时需要处理的业务逻辑的控制.

使用标准映射:

Mapper.CreateMap<Parent, ParentDTO>();
Mapper.CreateMap<ParentDTO, Parent>();
Mapper.CreateMap<Child, ChildDTO>();
Mapper.CreateMap<ChildDTO, Child>();
Run Code Online (Sandbox Code Playgroud)

它似乎从服务层工作得很好.域对象的子项完美映射到ChildDTO实例列表.

但是,当以相反的方式映射时,域模型上的集合未设置 - 因为它显然是只读的.似乎没有任何方法可以使用AutoMapper直接设置私有字段.我已经尝试了在这里和互联网的其他部分找到的各种建议.

最后,我想出了以下映射:

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));
                        });
Run Code Online (Sandbox Code Playgroud)

这符合我的要求.然而,我不禁觉得必须有一个更好的方法,而且我没有用现有的父母测试过这个,这个父母已经修改了孩子并且可能被添加和删除,所以我知道它实际上并不正确.最终,这个域模型是使用NHibernate持久化的,所以我不得不担心这一点.但是,一次一件事.:)

希望这可能会帮助遇到同样问题的其他人,也许正确解决问题的人能够纠正我.

Rob*_*est 0

我认为,如果您出于良好的业务逻辑原因而要保护属性,那么如果 AutoMapper 在进行映射时规避它们,那就不好了。在这种情况下,我更愿意放弃流畅的语法,并将创建逻辑放在自己的方法中,如下所示:

private Parent MapParentDTOToParent(ParentDTO source)
{
    var parent = new Parent();
    // Business logic here
    return parent
}
Run Code Online (Sandbox Code Playgroud)

进而:

Mapper.CreateMap<ParentDTO, Parent>().ConvertUsing(MapParentDTOToParent);
Run Code Online (Sandbox Code Playgroud)

我发现这比大量忽略声明更容易遵循。