Skip to content

Flattening ignores explicit type mapping rules #980

Description

@dcby

Setup

I have an Entity object with Props collection.

class Entity
{
  public string Name { get; set; } = default!;
  public List<EntityProp> Props { get; set; } = default!;
}

class EntityProp
{
  public string Key { get; set; } = default!;
  public string Value { get; set; } = default!;
}

My goal is to map it into a Dto object where items from Props collections become properties of destination object.

class Dto
{
  public string Name { get; set; } = default!;
  public string? Address { get; set; }
  public string? Description { get; set; }
  public string? Phone { get; set; }
}

For versatility I have two mapping. First is to flatten the Props into destination root and second to configure Props mapping.

config.NewConfig<Entity, Dto>().Map(e => e, e => e.Props);
config.NewConfig<List<EntityProp>, Dto>()
  .Map(e => e.Address, e => e.Get("Address"))
  .Map(e => e.Description, e => e.Get("Description"))
  .Map(e => e.Phone, e => e.Get("Phone"));

Problem

Second mapping rules are not obeyed during conversion. Is this pattern valid? Any workaround?

Complete code sample

using System.Collections.Generic;
using System.Linq;
using Mapster;

class Entity
{
  public string Name { get; set; } = default!;
  public List<EntityProp> Props { get; set; } = default!;
}

class EntityProp
{
  public string Key { get; set; } = default!;
  public string Value { get; set; } = default!;
}

class Dto
{
  public string Name { get; set; } = default!;
  public string? Address { get; set; }
  public string? Description { get; set; }
  public string? Phone { get; set; }
}

static class TestMapster
{
  public static void Test()
  {
    TypeAdapterConfig config = new();
    config.NewConfig<Entity, Dto>().Map(e => e, e => e.Props);
    config.NewConfig<List<EntityProp>, Dto>()
      .Map(e => e.Address, e => e.Get("Address"))
      .Map(e => e.Description, e => e.Get("Description"))
      .Map(e => e.Phone, e => e.Get("Phone"));

    Entity ent = new()
    {
      Name = "My entity",
      Props = [
        new() { Key = "Phone", Value = "12345678" }
      ],
    };

    Dto dto = ent.Adapt<Dto>(config);

    // dto.Name is mapped correctly and equals to "My entity".
    // Expected dto.Phone to be equal to "12345678",
    // but it is not mapped and is null
  }
}

static class ListExtensions
{
  // utility method as expression bodies are not allowed to have null propagating operator
  public static string? Get(this List<EntityProp> list, string key)
    => list.FirstOrDefault(e => e.Key == key)?.Value;
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions