A better way to use AutoMapper to flatten nested objects?

前端 未结 7 1762
执笔经年
执笔经年 2020-12-28 15:02

I have been flattening domain objects into DTOs as shown in the example below:

public class Root
{
    public string AParentProperty { get; set; }
    public         


        
7条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-28 15:33

    I wrote extension method to solve similar problem:

    public static IMappingExpression FlattenNested(
        this IMappingExpression expression,
        Expression> nestedSelector,
        IMappingExpression nestedMappingExpression)
    {
        var dstProperties = typeof(TDestination).GetProperties().Select(p => p.Name);
    
        var flattenedMappings = nestedMappingExpression.TypeMap.GetPropertyMaps()
                                                        .Where(pm => pm.IsMapped() && !pm.IsIgnored())
                                                        .ToDictionary(pm => pm.DestinationProperty.Name,
                                                                        pm => Expression.Lambda(
                                                                            Expression.MakeMemberAccess(nestedSelector.Body, pm.SourceMember),
                                                                            nestedSelector.Parameters[0]));
    
        foreach (var property in dstProperties)
        {
            if (!flattenedMappings.ContainsKey(property))
                continue;
    
            expression.ForMember(property, opt => opt.MapFrom((dynamic)flattenedMappings[property]));
        }
    
        return expression;
    }
    

    So in your case it can be used like this:

    var nestedMap = Mapper.CreateMap()
                          .IgnoreAllNonExisting();
    
    Mapper.CreateMap()
          .FlattenNested(s => s.TheNestedClass, nestedMap);
    

    IgnoreAllNonExisting() is from here.

    Though it's not universal solution it should be enough for simple cases.

    So,

    1. You don't need to follow flattening convention in destination's properties
    2. Mapper.AssertConfigurationIsValid() will pass
    3. You can use this method in non-static API (a Profile) as well

提交回复
热议问题