我想通过遍历所有映射的属性来重用c#Automapper的初始化映射(使用版本6.2.2)。
假设我有以下内容:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonDto
{
public int Id { get; set; }
public string FullName { get; set; }
}
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Person, PersonDto>()
.ForMember(dest => dest.FullName,
opt => opt.MapFrom(src => src.FirstName + " " + src.LastName));
};
Id
的循环行为符合预期:
var map = AutoMapper.Mapper.Configuration.FindTypeMapFor<Person, PersonDto>();
foreach (var propertyMap in map.GetPropertyMaps())
{
var destProp = propertyMap.DestinationProperty.Name; // = "Id"
var sourceMember = propertyMap.SourceMember.Name; // = "Id"
var sourceMembers = propertyMap.SourceMembers; // Count = 1
}
但是当我遍历FullName
属性映射时,我想实现propertyMap.SourceMembers导致两个SourceMembers FirstName
和LastName
:
var map = AutoMapper.Mapper.Configuration.FindTypeMapFor<Person, PersonDto>();
foreach (var propertyMap in map.GetPropertyMaps())
{
var destProp = propertyMap.DestinationProperty.Name; // = "FullName"
var sourceMember = propertyMap.SourceMember.Name; // = "LastName" (I don't care)
var sourceMembers = propertyMap.SourceMembers; // Count = 0 (want to achieve 2 for FirstName and LastName)
}
我的目标是基于初始化的自动映射器映射为orderBy
功能创建一个自动化的相似映射。所以我需要知道(a)顺序和(b)sourceMembers。在上述情况下,我想从其源成员FullName
和FirstName
(按此顺序)获取LastName
的映射。
是否可以正确地注册多个源成员,以便propertyMap.SourceMembers
产生所有映射的源成员?如果是,映射初始化应该是什么样?
PS:我不想手工编写orderBy映射,因为借助自动映射器,我已经有了映射。
答案 0 :(得分:0)
感谢Lucian Bargaoanu,我开发了以下 dirty 解决方法。
请注意,这是我第一次与解释表达式联系,所以请耐心接受我的解决方案的质量:
var map = AutoMapper.Mapper.Configuration.FindTypeMapFor<Person, PersonDto>();
foreach (var propertyMap in map.PropertyMaps)
{
var destProp = propertyMap.DestinationMember.Name; // = "FullName"
var sourceMember = propertyMap.SourceMember?.Name; // = "LastName" (I don't care)
var sourceMembers = propertyMap.SourceMembers.ToList();
if (sourceMembers.Count() == 0)
{
ResolveSourceMembersInOrder(sourceMembers,
propertyMap.CustomMapExpression.Body as BinaryExpression);
}
// sourceMembers now yield the two desired sourceMembers "FirstName" and "LastName"
}
public static void ResolveSourceMembersInOrder(List<MemberInfo> memberInfos, BinaryExpression expression)
{
if (memberInfos == null)
{
memberInfos = new List<MemberInfo>();
}
if (expression == null)
{
return;
}
var left = expression.Left;
if (left.NodeType == ExpressionType.MemberAccess)
{
memberInfos.Add(MemberVisitor.GetMemberPath(left).FirstOrDefault());
}
else
{
ResolveSourceMembersInOrder(memberInfos, left as BinaryExpression);
}
var right = expression.Right;
if (right.NodeType == ExpressionType.MemberAccess)
{
memberInfos.Add(MemberVisitor.GetMemberPath(right).FirstOrDefault());
}
else
{
ResolveSourceMembersInOrder(memberInfos, right as BinaryExpression);
}
}