根据源属性的条件,AutoMapper将目标设置为null

本文关键字:目标 设置 null AutoMapper 属性 条件 | 更新日期: 2023-09-27 18:26:47

我在两个对象之间进行映射,并且基于源的条件,我希望目标为null。

例如,以下是类:

public class Foo
{
    public int Code { get; set; }
    public string Name { get; set; }
}
public class Bar
{
    public string Name { get; set; }
    public string Type { get; set; }
}

还有我的地图:

Mapper.CreateMap<Foo, Bar>()
            .AfterMap((s, d) => { if (s.Code != 0) d = null; });

但它似乎忽略了AfterMap。栏已初始化,但具有所有默认属性。

如何让映射程序在代码不等于0的情况下返回null?

感谢

根据源属性的条件,AutoMapper将目标设置为null

一种可能的方法是-

class Converter : TypeConverter<Foo, Bar>
{
    protected override Bar ConvertCore(Foo source)
    {
        if (source.Code != 0)
            return null;
        return new Bar();
    }
}

static void Main(string[] args)
    {
        Mapper.CreateMap<Foo, Bar>()
            .ConvertUsing<Converter>();

        var bar = Mapper.Map<Bar>(new Foo
        {
            Code = 1
        });
        //bar == null true
    }

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

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<Foo, Bar>()
      .PreCondition(src => src.Code == 0);

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

我更喜欢自定义值解析器。这是我的看法。。。

public class CustomValueResolver : IValueResolver<Foo, Bar, string>
{
    public string Resolve(Foo source, Bar destination, string destMember, ResolutionContext context)
    {
        return source.Code != 0 ? null : "asd";
    }
}
public class YourProfile : Profile
{
    public YourProfile()
    {
        this.CreateMap<Foo, Bar>()
            .ForMember(dst => dst.Name, opt => opt.MapFrom<CustomValueResolver>())
            // ... 
            ;
    }
}