使用AutoMapper映射IListto (iis . collections . generic)

本文关键字:iis collections generic to 映射 AutoMapper IList TSource 使用 | 更新日期: 2023-09-27 18:02:14

我一直在试图解决这个问题一天了,现在已经没有了,所以我希望有人可能已经解决了这个问题。我找到的最接近的解决方案是如何使用AutoMapper简单地将NHibernate isset映射到IList,并通过AutoMapper将IList映射到iccollection,但仍然没有乐趣。

我有一个数据对象,看起来像:

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' to " iis . 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;
    }

但是我仍然得到相同的错误。任何帮助将非常感谢!

使用AutoMapper映射IList<TSource>to (iis . collections . generic)

您可以使用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子集合处理的一些重要方面进行更细粒度的控制(比如替换现有的集合内容,而不是像这个简化示例中那样覆盖集合引用)。

这是因为源和目标泛型类型参数在您正在映射的源和目标属性中不相同。你需要的映射是从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)));