使用AutoMapper将IList <tsource>映射到(Iesi.Collections.Generic)ISet <tdestination> </tdestination> </tsource>

时间:2011-07-17 07:22:48

标签: c# nhibernate automapper

我一直试图解决这个问题一天,但没有在哪里,所以我希望有人可能已经解决了这个问题。我找到的最接近解决方案的是How to simply map an NHibernate ISet to IList using AutoMapperMap IList to ICollection through AutoMapper,但仍然没有快乐。

我有一个看起来像这样的数据对象:

public class Parent
{
   public virtual ISet<Child> Children  {get; set; }
}

一个看似如下的业务对象:

public class ParentDto
{
   public IList<ChildDto> Children  {get; set; }
}

使用AutoMapper从数据映射到商家可以正常工作:

...
Mapper.CreateMap<Parent, ParentDto>();
Mapper.CreateMap<Child, ChildDto>();
...

ParentDto destination = CWMapper.Map<Parent, ParentDto>(source);

但是,当我从业务映射到数据时,我收到错误:

...
Mapper.CreateMap<ParentDto, Parent>();
Mapper.CreateMap<ChildDto, Child>();
...

Parent destination = CWMapper.Map<ParentDto, Parent>(source);
  

无法将'System.Collections.Generic.List'类型的对象强制转换为''Iesi.Collections.Generic.ISet'

我添加了自定义映射:

Mapper.CreateMap<ParentDto, Parent>()
      .ForMember(m => m.Children, o => o.MapFrom(s => ToISet<ChildDto>(s.Children)));

private static ISet<T> ToISet<T>(IEnumerable<T> list)
    {
        Iesi.Collections.Generic.ISet<T> set = null;

        if (list != null)
        {
            set = new Iesi.Collections.Generic.HashedSet<T>();

            foreach (T item in list)
            {
                set.Add(item);
            }
        }

        return set;
    }

但我仍然得到同样的错误。任何帮助都会受到极大的关注!

2 个答案:

答案 0 :(得分:7)

您可以使用AutoMapper的AfterMap()函数,如下所示:

Mapper.CreateMap<ParentDto, Parent>()
      .ForMember(m => m.Children, o => o.Ignore()) // To avoid automapping attempt
      .AfterMap((p,o) => { o.Children = ToISet<ChildDto, Child>(p.Children); });

AfterMap()允许对NHibernate子集合处理的一些重要方面进行更细粒度的控制(如替换现有集合内容,而不是像在此简化示例中那样覆盖集合引用)。

答案 1 :(得分:2)

这是因为源映射和目标泛型类型参数在您映射的源和目标属性中不相同。您需要的映射是从IEnumerable<ChildDto>ISet<Child>,可以推广到从IEnumerable<TSource>ISet<TDestination>而不是IEnumerable<T>ISet<T>的映射。您需要在转换功能中考虑到这一点(实际上,您在问题的标题中有正确的答案..)。

ToISet方法应该类似于下面发布的方法。它还使用AutoMapper将ChildDto映射到Child

private static ISet<TDestination> ToISet<TSource, TDestination>(IEnumerable<TSource> source)
{
    ISet<TDestination> set = null;
    if (source != null)
    {
        set = new HashSet<TDestination>();

        foreach (TSource item in source)
        {
            set.Add(Mapper.Map<TSource, TDestination>(item));
        }
    }
    return set;
}

然后您可以按如下方式更改地图定义:

Mapper.CreateMap<ParentDto, Parent>().ForMember(m => m.Children,
          o => o.MapFrom(p => ToISet<ChildDto, Child>(p.Children)));