簡體   English   中英

AutoMapper 使用數組列表的嵌套屬性映射

[英]AutoMapper to Map with nested property of List of array

我有一個 A 類,我需要用 C 類映射

public class A{
   public string Name {get; set;}
   public List<B> Address {get; set;}}


public class B{
    public string streetName{get; set;}
    public int Number {get; set;}}

我需要將此映射到 C 類

public class C{
    public int id{get;set;}
    public List<MapAddressData> MapAddressData{get; set;}
    public DateTime DateCreated {get; set;}}

public class MapAddressData{
   public string Name {get; set;}
   public string streetName {get; set;}
   public int Number{get; set;}}

所以我需要使用自動映射器將 A 類中的地址列表映射到 C 類中的 MapAddressData 列表。我不明白如何使用 for 循環進行映射,因為對於特定名稱,我們有很多地址,n 必須映射對C類中的'MapAddressData'類一一進行。有沒有辦法實現這一點?

我不確定是否有更清潔的方法可以做到這一點,但您可以像這樣配置 AutoMapper:

cfg.CreateMap<A, C>()
    .BeforeMap((src, _, ctx) => ctx.Options.Items[$"__{nameof(A)}"] = src)
    .ForMember(dst => dst.MapAddressData, mo => mo.MapFrom(src => src.Address));

cfg.CreateMap<B, MapAddressData>()
    .ForMember(dst => dst.Name, mo => mo.MapFrom(new MapAddressNameResolver()));

使用.BeforeMap我們使用鍵"__A"將源值存儲在映射上下文項集合中。

接下來,我們告訴 AutoMapper 它應該使用源對象的Address屬性將MapAddressData映射到目標對象。

然后我們在BMapAddressData之間創建一個映射。 對於目標對象的Name屬性,我們使用自定義解析器: MapAddressNameResolver來檢索值:

private class MapAddressNameResolver : IValueResolver<B, MapAddressData, string>
{
    public string Resolve(B source, MapAddressData destination, string destMember, ResolutionContext context)
    {
        if (context.Options.Items.TryGetValue($"__{nameof(A)}", out var parent) 
                && parent is A sourceParent)
        {
            return sourceParent.Name;
        }
        throw new InvalidOperationException("Address cannot be mapped to MapAddressData indepdendently of A to C.");
    }
}

這會查看映射上下文項集合,並嘗試檢索針對鍵"__A"存儲的值。 如果它確實是A的一個實例,我們返回它的Name屬性。

如果其中任何一個不正確,我們會拋出一個異常,以便我們知道如果將來有人嘗試在其他上下文中使用此映射而不添加適當的支持,則此映射已失敗。


完整示例

public static void TestMethod()
{

    var mapperConfig = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<A, C>()
            .BeforeMap((src, _, ctx) => ctx.Options.Items[$"__{nameof(A)}"] = src)
            .ForMember(dst => dst.MapAddressData, mo => mo.MapFrom(src => src.Address));

        cfg.CreateMap<B, MapAddressData>()
            .ForMember(dst => dst.Name, mo => mo.MapFrom(new MapAddressNameResolver()));
    });
    var mapper = mapperConfig.CreateMapper();

    var sourceObject = new A()
    {
        Name = "bob",
        Address = new List<B>()
    {
        new B()
        {
            Number = 5,
            streetName = "bob street"
        },
        new B()
        {
            Number = 125,
            streetName = "somewhere street"
        }
    }
    };

    var mappedObject = mapper.Map<C>(sourceObject);
}

private class MapAddressNameResolver : IValueResolver<B, MapAddressData, string>
{
    public string Resolve(B source, MapAddressData destination, string destMember, ResolutionContext context)
    {
        if (context.Options.Items.TryGetValue($"__{nameof(A)}", out var parent) && parent is A sourceParent)
        {
            return sourceParent.Name;
        }
        throw new InvalidOperationException("Address cannot be mapped to MapAddressData indepdendently of A to C.");
    }
}

例如,您有 A 類的數據,例如

名稱=用戶 1

地址1

街道名稱 = 街道名稱 1 編號 = 編號 1

地址2

街道名稱 = 街道名稱 2 編號 = 編號 2

地址3

街道名稱 = 街道名稱 3 編號 = 編號 3

對於多個名稱,您必須進行嵌套循環來訪問 A 類對象中的每個數據,同時考慮我們有MapAddressData類的對象作為 mappedAddress。

foreach(var item from ClassAObject)
{
   mappedAddress.Name = item.Name;
   foreach(var address from item.Address)
   {
      mappedAddress.streetName = address.streetName;
      mappedAddress.Number= address.Number;
      >> Here you will be adding this mappedAddress objcect in mappedAddress from class C.

   }
}

附加代碼示例只是為了獲得更多說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM