映射子对象时,AutoMapper传递父引用

时间:2011-03-17 15:48:51

标签: collections automapper parent-child

我正在尝试使用AutoMapper将从Web服务接收的一些DTO(数据协定)对象映射到我的业务对象中。根DTO对象包含子对象的集合。我的业务对象还有子业务对象的子集合。为了让AutoMapper工作,我必须在业务对象的collection属性中包含一个setter,否则该collection将始终为空。另外,我必须在集合类型中添加一个默认构造函数。因此,在我看来,AutoMapper正在实例化一个新的集合对象,填充它并设置为我的业务对象的集合属性。

虽然这一切都很好,但我还有一些额外的逻辑,当创建集合并使默认构造函数失败时,必须将其连接起来。从本质上讲,我正在建立父子关系,并将一些事件连接起来,以便它们从孩子到父母一起冒泡。

我想要做的是让AutoMapper简单地将子对象从DTO的集合映射到我的BO上的现有集合。换句话说,跳过创建新集合并简单地使用业务对象已有的集合。

有没有办法轻松实现这个目标?!?!?

更新

也许更好的问题,更简单的解决我的问题的方法是,是否可以定义AutoMapper在实例化时传递给集合的参数?我的子集合定义如下:

public class ChildCollection : Collection<ChildObjects>
{
    public ChildCollection(ParentObject parent) { Parent = parent; }
}

如果我可以将AutoMapper配置为使用此构造函数并传入正确的对象,那将是完美的!

另一个更新

为了清楚起见,以下是问题空间中的其他类:

public class ParentObject
{
    private ChildCollection _children;

    public ChildCollection Children
    {
        get
        {
            if (_children == null) _children = new ChildCollection(this);

            return _children;
        }
    }
}

public class ParentDTO
{
    public ICollection<ChildDTO> Children { get; set; }
}

public class ChildDTO
{
    public String SomeProperty { get; set; }
}

我以这种方式配置AutoMapper:

Mapper.CreateMap<ParentDTO, ParentObject>();
Mapper.CreateMap<ChildDTO, ChildObject>();

这样做,我必须在ParentObject中的Children属性和ChildCollection的默认(无参数)构造函数中添加一个setter。虽然我可以解决定义父子关系的需要,但似乎期望AutoMapper支持在创建子集合时配置映射以使用特定构造函数。像这样:

Mapper.CreateMap<ParentDTO, ParentObject>()
    .ForMember(obj => obj.Children, opt.MapFrom(dto => dto.Children))
    .ConstructUsing(col => new ChildCollection(obj));

请注意,我传入的是对象“obj”,它是被映射的ParentObject实例。

3 个答案:

答案 0 :(得分:7)

事实证明,答案一直都在那里。 UseDestinationValue选项完全符合我的要求。

此选项指示AutoMapper使用目标对象上的现有属性,并将任何子属性或集合项映射到该对象,而不是创建新的代理对象。

所以,这就是我在申请中所要做的一切:

Mapper.CreateMap<ParentDTO, ParentObject>()
    .ForMember(obj => obj.Children,
           opt.UseDestinationValue());

而且,瞧!现在,我可以使用父引用实例化子集合,并在将每个项目添加到集合中时将引用设置回父项。

答案 1 :(得分:0)

如果我了解您的问题,您应该可以使用此答案中所述的ConstructUsingAutomapper - how to map to constructor parameters instead of property setters

答案 2 :(得分:0)

对于带有AutoMapper.Collection.EntityFrameworkCore或EntityFramework的EntityFramework(mvc或核心),可以通过将子ID与以下目标对象ID匹配来实现

    _config = new MapperConfiguration(cfg =>
    {
        cfg.AddCollectionMappers();

        cfg.CreateMap<Order, OrderDto>()
        .EqualityComparison((odto, o) => odto.Id == o.Id)
        .ReverseMap();
        cfg.CreateMap<OrderDetail, OrderDetailDto>().EqualityComparison((odto, o) => odto.Id == o.Id).ReverseMap(); 
    });

在我的情况下,我有一个List<Order>,并且如果我想将List<OrderDetails>映射到List<Order>与{{ 1}}不可能映射到配置。但是我是通过像上面这样分开来完成的。我可以像下面一样使用它

List<OrderDto>

有一种从顶部配置它的方法,但是它非常困难,我现在找不到它。但这可能是某人的保留。

在我看来,对于那些映射配置,Mapster比autofac强大。