我没有看到能够解决我的问题的答案:我只是将“ForMember”替换为“ForCtorParm”。
您需要将构造函数参数提供为字符串,因此变成:
CreateMap<BFrom, ATo>()
.ForCtorParam("ExtraId", opt => opt.MapFrom(src => src.DbExtraId))
.ForCtorParam("Id", opt => opt.MapFrom(src => default(Guid)));
需要注意以下几点:
- 你需要提供所有参数,否则(隐式创建的)构造函数将无法被调用。
- "Ignore"方法不再存在。你不能选择忽略构造函数参数。
- ReverseMap不起作用:一旦编译完成,就会有一个构造函数,其参数名称刚好与属性的名称和类型相同。但在这个阶段,automapper不知道这种情况。记录只被编译为类(带有一些特殊属性)
你可以通过利用生成的构造函数参数名和属性名/类型始终相同的事实来使生活更轻松。你可以添加一个扩展方法。
public static class AutoMapperExtensions
{
public static IMappingExpression<TSource, TDestination> ForCtorParm<TSource, TDestination, TMember>(
this IMappingExpression<TSource, TDestination> mappingExpression,
Expression<Func<TDestination, TMember>> destinationMember,
Action<ICtorParamConfigurationExpression<TSource>> paramOptions)
{
var memberInfo = FindProperty(destinationMember);
var memberName = memberInfo.Name;
return mappingExpression
.ForCtorParam(memberName, paramOptions);
}
private static MemberInfo FindProperty(LambdaExpression lambdaExpression)
{
Expression expressionToCheck = lambdaExpression.Body;
while (true)
{
switch (expressionToCheck)
{
case MemberExpression { Member: var member, Expression: { NodeType: ExpressionType.Parameter or ExpressionType.Convert } }:
return member;
case UnaryExpression { Operand: var operand }:
expressionToCheck = operand;
break;
default:
throw new ArgumentException(
$"Expression '{lambdaExpression}' must resolve to top-level member and not any child object's properties. You can use ForPath, a custom resolver on the child type or the AfterMap option instead.",
nameof(lambdaExpression));
}
}
}
}
这样可以让你更加类型安全地进行操作:
CreateMap<BFrom, ATo>()
.ForCtorParam(dest => dest.ExtraId, opt => opt.MapFrom(src => src.DbExtraId))
.ForCtorParam(dest => dest.Id, opt => opt.MapFrom(src => default(Guid)));