使用AutoMapper将IList<TSource>映射到(Iesi.Collections.Generic) ISet<TDestination>

8
我已经尝试了一整天来解决这个问题,但是没有任何进展,所以希望有人之前解决过类似的问题。我找到的最接近解决方案是如何使用AutoMapper将NHibernate ISet简单映射为IList通过AutoMapper将IList映射到ICollection,但仍然无法解决问题。
我的数据对象看起来像这样:
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;
    }

但我仍然收到相同的错误。任何帮助都将不胜感激!

Mapper.CreateMap<List<Child>, ISet<Child>>() .ConstructUsing(c => ToISet<ChildDto>(c)); 也不起作用。 - Mark Vickery
2个回答

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子集合处理的一些重要方面,例如替换现有集合内容而不是像在这个简化的例子中覆盖集合引用。


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)));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接