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

Mar*_*ery 8 c# nhibernate automapper

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

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

public class Parent
{
   public virtual ISet<Child> Children  {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和一个看起来像这样的业务对象:

public class ParentDto
{
   public IList<ChildDto> Children  {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用AutoMapper从Data to Business映射工作正常:

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

ParentDto destination = CWMapper.Map<Parent, ParentDto>(source);
Run Code Online (Sandbox Code Playgroud)

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

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

Parent destination = CWMapper.Map<ParentDto, Parent>(source);
Run Code Online (Sandbox Code Playgroud)

无法将'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;
    }
Run Code Online (Sandbox Code Playgroud)

但我仍然得到同样的错误.任何帮助都会很大的帮助!

and*_*yqp 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); });
Run Code Online (Sandbox Code Playgroud)

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


Can*_*cer 2

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

ToISet 方法应该类似于下面发布的方法。它也使用 AutoMapper 来映射ChildDtoChild.

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;
}
Run Code Online (Sandbox Code Playgroud)

然后您可以更改地图定义,如下所示:

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