How do I conditionally set the destination object to null using automapper

匆匆过客 提交于 2019-12-11 03:15:23

问题


I am trying to do something like this:

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

However, the assigned value of link is not used in any execution path.
I would like linkOutput to be null, but it is not.
How would I make the destination object null?

Details of objects involved:

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
}

Here's a fiddle: http://dotnetfiddle.net/hy2nIa


回答1:


I created the following extension method to solve this problem.

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

For the case in question, it can be used like this:

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

Now, if the condition fails, the mapper will return null; otherwise, it will return the mapped object.




回答2:


This is the solution I used in the end, it was a bit more manual internally, but does not require any extra plumbing.

If anyone has a more elegant solution, it would be appreciated.

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



回答3:


I think that will have to be done outside the mapping. Since AutoMapper requires an instance to map to, setting the destination to null seems like it should go outside the mapping.

I would instead do something like:

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


来源:https://stackoverflow.com/questions/23209101/how-do-i-conditionally-set-the-destination-object-to-null-using-automapper

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!