具有分层属性的Automapper Map列表

时间:2018-03-17 20:47:28

标签: c# automapper

我在将具有多层属性的对象映射到具有单层属性的对象时遇到了一些麻烦。这是一个例子:

我的目的地课程

public class Part
{
    public string Name { get; set; }
    public string PartNumber { get; set; }
    public string Position { get; set; }
    public IList<Part> ReplacedBy { get; set; } = new List<Part>();

}

我的源类

public class PartType
{
    public string PartNumber { get; set; }
    public PartInformationType Part { get; set; }

}

public class PartInformationType
{
    public string Position { get; set; }
    public string Name { get; set; }
    public IList<PartType> ReplacedBy { get; set; } = new List<PartType>();

}

请注意,真实对象在每个图层中都有更多属性,因此在每个受影响的属性上执行ForMember()会很麻烦。有没有自动化的方式为我做这个?

预期结果: 这给了我预期的结果,但仅限于一代零件,比如每个被替换的零件被另一个零件替换了10代,很快变得无法管理

var part = Mapper.DynamicMap<Part>(result);
part.ReplacedBy = new List<ReplacementPart>();
foreach (var partType in result.ReplacedBy)
{
    var replacementPart = Mapper.DynamicMap<ReplacementPart(partType.Part);
    replacementPart.Name= partType.Name;
    replacementPart.Position= partType.Position;
    part.ReplacedBy.Add(replacementPart);
}

1 个答案:

答案 0 :(得分:0)

这是一个有趣的问题,我碰巧在我的一个项目中解决了一个非常相似的问题,所以希望我的答案也能满足你的需求,或者至少让你走上正轨。我已根据您的情况调整了示例代码。

我的目的地模特课(与你的很相似):

public class PartModel
{
    public string Name { get; set; }
    public string PartNumber { get; set; }
    public string Position { get; set; }
    public List<PartModel> ReplacedBy { get; set; }
}

我的两个源类(也与你的几乎相同)

public class PartEntity
{
    public string PartNumber { get; set; }
    public PartEntityInformation PartEntityInformation { get; set; }
}

public class PartEntityInformation
{
    public string Position { get; set; }
    public string Name { get; set; }
    public List<PartEntity> ReplacedBy { get; set; }
}

我已经定义了一个静态EntityMap,其中包含两个映射的配置。正如我在你的问题的评论中提到的 - 我没有指定任何特定的成员映射配置,因为Automapper将按惯例映射,因为我的源和目标对象之间的属性名称匹配。

public static class EntityMap
{
    public static IMapper EntityMapper { get; set; }

    static EntityMap()
    {
        EntityMapper = new MapperConfiguration(config =>
        {
            config.CreateMap<PartEntity, PartModel>();
            config.CreateMap<PartEntityInformation, PartModel>();
        }).CreateMapper();
    }
}

您可以使用下面的EntityMap。这里没什么特别的,它只会让我得到只有PartNumber属性被映射的基本模型。

        var rootPart = GetPart();
        var rootPartModel = EntityMap.EntityMapper.Map<PartModel>(rootPart);

为了获得ReplacedBy部分的嵌套映射,您可以使用递归(这是我在项目中解决这个嵌套映射要求的方法,可能有更好的解决方案)。在此方法中,我递归地将嵌套的子对象映射到其目标对象,因为初始映射将为我提供嵌套的ReplacedBy列表中的项目数。

    public static void MapRecursively(PartModel partModel, PartEntity partEntity)
    {
        EntityMap.EntityMapper.Map(partEntity.PartEntityInformation, partModel);

        if (partEntity.PartEntityInformation.ReplacedBy == null
            || partEntity.PartEntityInformation.ReplacedBy.Count == 0) return;

        for (var i = 0; i < partModel.ReplacedBy.Count; i++)
        {
            MapRecursively(partModel.ReplacedBy[i], partEntity.PartEntityInformation.ReplacedBy[i]);
        }
    }

所以你现在可以使用rootPartrootPartModel这个递归方法来映射其余的嵌套对象。

        MapRecursively(rootPartModel, rootPart);

这应该是开箱即用的,我在下面提供了GetRootPart()方法规范,因为它只是我使用过的示例数据。

   private static PartEntity GetPart()
    {
        var partEntityInfo = new PartEntityInformation
        {
            Name = "SomeName",
            Position = "2",
            ReplacedBy = new List<PartEntity>
            {
                new PartEntity
                {
                    PartNumber = "22",
                    PartEntityInformation = new PartEntityInformation
                    {
                        Name = "SomeSubName"
                    }
                },
                new PartEntity
                {
                    PartNumber = "33",
                    PartEntityInformation = new PartEntityInformation
                    {
                        Name = "33SubName",
                        Position = "33SubPosition",
                        ReplacedBy = new List<PartEntity>
                        {
                            new PartEntity
                            {
                                PartNumber = "444",
                                PartEntityInformation = new PartEntityInformation
                                {
                                    Name = "444SubSubname"
                                }
                            }
                        }
                    }
                }

            }
        };
        var part = new PartEntity
        {
            PartNumber = "1",
            PartEntityInformation = partEntityInfo
        };
        return part;
    }