AutoMapper一个类中的多个类ViewModel具有属性来自每个类

时间:2018-05-28 16:51:00

标签: c# linq automapper

我有这样的课程

public class ClassOne
{
    public string Id { get; set; }

    //...many others properties

} 

public class ClassTwo
{
    public string Id { get; set; }

    //...many others properties differents from classeOne

    public string Email { get; set; }
} 

public class ClassThree
{
    public string Id { get; set; }

    //...many others properties differents from classeOne and classTwo

    public string Email { get; set; }
} 


public class ViewModel
{
    //...same properties as classeOne

    public string EmailClasseTwo { get; set; }
    public string EmailClassThree { get; set; }
} 

public class ObjectReturnByLinqQuery
{
   public ClassOne classOne { get; set; }    
   public ClassTwo classTwo { get; set; }
   public ClassThree classThree { get; set; }
} 

如何在ViewModelObjectReturnByLinqQuery之间创建地图而不为每个类逐个成员?

类似

config.CreateMap<ObjectReturnByLinqQuery, ViewModel>()
.ForMember(ViewModel => ViewModel.EmailClasseTwo , ModelDB => ModelDB.MapFrom(src => src.ClasseTwo.Email))
.ForMember(ViewModel => ViewModel.EmailClasseThree , ModelDB => ModelDB.MapFrom(src => src.ClasseThree.Email))

并且所有其他成员从src.ClassOne

获取它们

1 个答案:

答案 0 :(得分:1)

不幸的是,没有开箱即用的方法。但您可以像这样创建Custom Naming Convention

using AutoMapper;
using AutoMapper.Configuration.Conventions;
using System.Reflection;

class CustomMapMember : IChildMemberConfiguration
{
    Dictionary<TypePair, List<PropertyInfo>> map = new Dictionary<TypePair, List<PropertyInfo>>();

    public CustomMapMember Add(Type destType, Type sourceType, string sourcePropertyName)
    {
        var key = new TypePair(sourceType, destType);
        if (!map.TryGetValue(key, out var properties))
            map.Add(key, properties = new List<PropertyInfo>());
        properties.Add(sourceType.GetProperty(sourcePropertyName));
        return this;
    }

    public bool MapDestinationPropertyToSource(ProfileMap options, TypeDetails sourceType, Type destType, Type destMemberType, string nameToSearch, LinkedList<MemberInfo> resolvers, IMemberConfiguration parent)
    {
        if (map.TryGetValue(new TypePair(sourceType.Type, destType), out var properties))
        { 
            foreach (var property in properties)
            {
                resolvers.AddLast(property);
                var memberType = options.CreateTypeDetails(property.PropertyType);
                if (parent.MapDestinationPropertyToSource(options, memberType, destType, destMemberType, nameToSearch, resolvers))
                    return true;
                resolvers.RemoveLast();
            }
        }
        return false;
    }
}

然后像这样使用它:

config.AddMemberConfiguration().AddMember<CustomMapMember>(m =>
    // Configure the custom mappings here
    m.Add(typeof(ViewModel), typeof(ObjectReturnByLinqQuery), nameof(ObjectReturnByLinqQuery.classOne))
);

config.CreateMap<ObjectReturnByLinqQuery, ViewModel>()
    .ForMember(ViewModel => ViewModel.EmailClasseTwo, ModelDB => ModelDB.MapFrom(src => src.classTwo.Email))
    .ForMember(ViewModel => ViewModel.EmailClassThree, ModelDB => ModelDB.MapFrom(src => src.classThree.Email));