【问题标题】:Mapping "LinkedList" with AutoMapper使用 AutoMapper 映射“LinkedList”
【发布时间】:2012-03-15 21:08:10
【问题描述】:

我有链表的情况。我的 DTO 看起来像这样 -

public class DTOItem
{
    public string ID
    {
        get;
        set;
    }

    public int? UniqueId
    {
        get;
        set;
    }

    public string Payload
    {
        get;
        set;
    }

    //How do I map this guy? It is list of same type.
    public List<DTOItem> RelatedItems
    {
        get;
        set;
    }
}

如何使用 AutoMapper 映射这个人?我能够映射班级的其他成员。数据是从另一个类的集合对象映射的,该集合对象具有与该类不同的一组不同的成员。

public List<DTOItem> RelatedItems
{
    get;
    set;
}

提前致谢。

更新:这是代码 - 拉斐尔,这是代码:

源对象:

public class ResultsSet
{
    public int? ResultId
    {
        get;
        set;
    }

    public int UID
    {
        get;
        set;
    }

    //Returns large XML string
    public string ResultBlob
    {
        get;
        set;
    }

    public RelatedItems[] RelatedSet
    {
        get;
        set;
    }
}

public class RelatedItems
{
    public int Item_ID
    {
        get;
        set;
    }

    public int Relationship_ID
    {
        get;
        set;
    }

    public string Description
    {
        get;
        set;
    }
}

这里的映射是代码:

Mapper.CreateMap<ResultSet, DTOItem>()
            .ForMember(dest => dest.ID, opt => opt.MapFrom(src => src.ResultID.GetValueOrDefault(0)))
            .ForMember(dest => dest.UniqueId, opt => opt.MapFrom(src => src.UID))
            .ForMember(dest => dest.Payload, opt => opt.MapFrom(src => src.ResultBlob));

            /*
                How do I map RelatedSet to RelatedItems here?
            */

Mapper.Map(result, returnResult);

再次感谢。

【问题讨论】:

  • 你能给出“源”类和你尝试了什么(映射)吗?
  • 嗨 Raphael,我已经添加了源类。
  • 这不是链表……这个数据里有循环引用吗?
  • 是的,你说得对,这不是一个链表。它更像是一棵树。不,不会有任何循环引用。 RelatedSet 在集合中可以有零个或多个。而且,RelatedSet 集合中的项目将不再有子 DTOItem。

标签: c# automapper


【解决方案1】:

无需为此使用 AutoMapper。 对于非循环、相对平坦的数据,应该这样做:

static Func<RelatedItems, DTOItem> MapRelated(IEnumerable<ResultsSet> all) {
    var map = MapResultSet(all);
    return relatedItem => map(all.First(x => x.UID == relatedItem.Item_ID));
}

static Func<ResultsSet, DTOItem> MapResultSet(IEnumerable<ResultsSet> all) {
    return s => 
        new DTOItem {
            ID = s.ResultId.GetOrElse(0).ToString(),
            UniqueId = s.UID,
            Payload = s.ResultBlob,
            RelatedItems = (s.RelatedSet ?? new RelatedItems[0]).Select(MapRelated(all)).ToList()
        };
}

示例用法:

var data = new[] { 
    new ResultsSet {
        UID = 1,
        RelatedSet = new[] {
            new RelatedItems { Item_ID = 2 },
            new RelatedItems { Item_ID = 3 },
        },
    },
    new ResultsSet {
        UID = 2,
    },
    new ResultsSet {
        UID = 3,
    },
};
var items = data.Select(MapResultSet(data)).ToList();
Debug.Assert(items.Count == 3);
Debug.Assert(items[0].UniqueId == 1);
Debug.Assert(items[1].UniqueId == 2);
Debug.Assert(items[2].UniqueId == 3);
Debug.Assert(items[0].RelatedItems.Count == 2);
Debug.Assert(items[0].RelatedItems[0].UniqueId == items[1].UniqueId);
Debug.Assert(items[0].RelatedItems[1].UniqueId == items[2].UniqueId);

我假设 Item_ID 是 UID 的“关键”,否则只需调整 MapRelated

一般来说,我认为 AutoMapper 仅在您必须将非类型化数据映射到类型化数据时才有用,即使在这种情况下,我在使用它之前也会认真考虑。否则,一些 LINQ 代码会更简单,类型更安全。

【讨论】:

  • 还有另一个类扩展了这个类,它有 30 多个需要复制值的成员。而且,在这种情况下, List 和 string[] 等之间存在映射。您建议如何做到这一点?
  • @user1244179 :1.你没有在你的问题中指定,所以它应该是一个新问题。 2.你可以只写代码,这很简单。如果您的意思是您需要在编写 30 行代码和破坏类型系统之间做出选择,我会选择 30 行代码。如果您的领域中有常见的转换,您可以将其抽象为(可能是高阶)函数。 3. 必须将很多类映射到相似的类是一种代码味道,您可能需要修改为什么需要这样做...
猜你喜欢
  • 1970-01-01
  • 2011-08-25
  • 2013-05-09
  • 2011-08-01
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 2017-03-13
相关资源
最近更新 更多