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

时间:2014-04-22 01:59:57

标签: c# automapper

我正在尝试做这样的事情:

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

3 个答案:

答案 0 :(得分:5)

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

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

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,
                };
            });

答案 1 :(得分:1)

我认为必须在映射之外完成。由于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);

答案 2 :(得分:0)

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

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;否则,映射器将返回null。否则,它将返回映射的对象。