如何使用automapper有条件地将目标对象设置为null

本文关键字:目标对象 设置 null 何使用 automapper 有条件 | 更新日期: 2023-09-27 17:59:20

我正在尝试这样做:

AutoMapper.Mapper.CreateMap<UrlPickerState, Link>()
        .ForMember(m=>m.OpenInNewWindow,map=>map.MapFrom(s=>s.NewWindow))
        .AfterMap((picker, link) => link = !string.IsNullOrWhiteSpace(link.Url)?link:null) ;
var pickerState = new UrlPickerState();
var linkOutput = AutoMapper.Mapper.Map<Link>(pickerState);

然而,link的赋值不用于任何执行路径
我希望linkOutput为null,但它不是
如何使目标对象为null?

涉及对象的详细信息:

public class Link
{
    public string Title { get; set; }
    public string Url { get; set; }
    public bool OpenInNewWindow { get; set; }
}
public class UrlPickerState
{
    public string Title { get; set; }
    public string Url { get; set; }
    public bool NewWindow { get; set; }
    //.... etc
}

这是一把小提琴:http://dotnetfiddle.net/hy2nIa

如何使用automapper有条件地将目标对象设置为null

这是我最终使用的解决方案,它在内部有点手动,但不需要任何额外的管道。

如果有人有更优雅的解决方案,我们将不胜感激。

config.CreateMap<UrlPickerState, Link>()
            .ConvertUsing(arg =>
            {
                if (string.IsNullOrWhiteSpace(arg.Url))
                {
                    return null;
                }
                return new Link()
                {
                    Url = arg.Url,
                    OpenInNewWindow = arg.NewWindow,
                    Title = arg.Title,
                };
            });

我创建了以下扩展方法来解决这个问题。

public static IMappingExpression<TSource, TDestination> PreCondition<TSource, TDestination>(
   this IMappingExpression<TSource, TDestination> mapping
 , Func<TSource, bool> condition
)
   where TDestination : new()
{
   // This will configure the mapping to return null if the source object condition fails
   mapping.ConstructUsing(
      src => condition(src)
         ? new TDestination()
         : default(TDestination)
   );
   // This will configure the mapping to ignore all member mappings to the null destination object
   mapping.ForAllMembers(opt => opt.PreCondition(condition));
   return mapping;
}

对于有问题的情况,它可以这样使用:

Mapper.CreateMap<UrlPickerState, Link>()
      .ForMember(dest => dest.OpenInNewWindow, opt => opt.MapFrom(src => src.NewWindow))
      .PreCondition(src => !string.IsNullOrWhiteSpace(src.Url));

现在,如果条件失败,映射器将返回null;否则,它将返回映射的对象。

我认为这必须在映射之外完成。由于AutoMapper需要一个实例来映射到,因此将目标设置为null似乎应该在映射之外。

相反,我会做一些类似的事情:

AutoMapper.Mapper.CreateMap<UrlPickerState, Link>()
        .ForMember(m=>m.OpenInNewWindow,map=>map.MapFrom(s=>s.NewWindow));
var pickerState = new UrlPickerState();
Link linkOutput = null;
if(!string.IsNullOrWhiteSpace(pickerState.Url))  // or whatever condition is appropriate
    linkOutput = AutoMapper.Mapper.Map<Link>(pickerState);