2011-11-08 32 views
16

这不是一个问题,因为我找到了一种方法来做我想做的事情,但似乎应该有更好的方法来做到这一点。我到处搜索,没有发现任何东西。使用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); 
    } 
} 

public class Child 
{ 
    public Parent Parent { get; set; } 
} 

(我省略性质无关的问题和错误校验守着清楚起见...)

public class ParentDTO 
{ 
    List<ChildDTO> Children = new List<ChildDTO>(); 
} 

public class ChildDTO 
{ 
} 

原因我使用的方法来增加孩子的收集是维护需要在添加一个孩子要处理的业务逻辑的控制。

拥有标准映射:

Mapper.CreateMap<Parent, ParentDTO>(); 
Mapper.CreateMap<ParentDTO, Parent>(); 
Mapper.CreateMap<Child, ChildDTO>(); 
Mapper.CreateMap<ChildDTO, Child>(); 

这似乎很好地工作从服务层来了。域对象的子项完全映射到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)); 
         }); 

这工作,因为我需要的。然而,我不禁感到必须有更好的方法,而且我还没有用一个已经修改过子代并可能添加和删除的现有父级进行测试,所以我知道它实际上并不正确。最终,这个领域模型是使用NHibernate持久化的,所以我不必担心这一点。但是,一次只有一件事。 :)

希望这可以帮助别人谁是遇到了同样的问题,也许有人谁的解决得当就能指正。

+2

+1你的aftermap解决方案救了我。 –

+0

很酷的解决方案。我会借它:-) – LeftyX

+0

用AfterMap的好主意。使用Source和Destination对象比使用ResolutionResult和类似的东西容易得多! – Andrei

回答

0

我认为,如果你要保护性能良好的业务逻辑的理由那么这将是坏的,如果AutoMapper做它的映射时避开他们。在这样的情况下,我宁愿放弃流利的语法并把创建逻辑在其自己的方法是这样的:

private Parent MapParentDTOToParent(ParentDTO source) 
{ 
    var parent = new Parent(); 
    // Business logic here 
    return parent 
} 

然后:

Mapper.CreateMap<ParentDTO, Parent>().ConvertUsing(MapParentDTOToParent); 

我觉得这是容易按照比有很多的忽略声明。