我一直在寻找无处不在:stackoverflow,automapper文档,互联网,并且无法找到关于此信息的任何信息,即使这似乎是一个非常常见的问题。
我的映射:
CreateMap<StatusLevelDTO, StatusLevel>()
.ForAllMembers(opt => opt.Condition(src => src != null));
这不起作用,因为src代表源对象(StatusLevelDTO),而不是源属性(我认为)。
更具体地说,如果我将ObjectA映射到ObjectB,ObjectA.SomeValue为null且ObjectB.SomeValue为2,我希望目标对象保持其值(2)。
我已经看到了这个问题:Automapper skip null values with custom resolver并尝试了前两个答案,但它们似乎都已过时版本6了。
有没有办法在Automapper 6中实现这一点?我准确地使用6.0.2。
答案 0 :(得分:40)
方法Condition
现在有五个重载,其中一个重载接受类型为
Func<TSource, TDestination, TMember, bool>
此TMember参数是源成员。因此,您可以检查源成员是否为null:
CreateMap<StatusLevelDTO, StatusLevel>()
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
答案 1 :(得分:5)
解决方案here适用于我的项目,该项目使用的是AutoMapper 6.0.2。在之前使用AutoMapper 4的项目中,我使用了IsSourceValueNull来实现相同的行为。
我对原始解决方案做了一些小改动。我没有检查要映射的属性的类型,而是在ForAllPropertyMaps中设置过滤器以检查源对象的类型,以便自定义解析器仅应用于该源对象的映射。但是过滤器可以根据需要设置为任何东西。
var config = new MapperConfiguration(cfg =>
{
cfg.ForAllPropertyMaps(
pm => pm.TypeMap.SourceType == typeof(<class of source object>),
(pm, c) => c.ResolveUsing<object, object, object, object>(new IgnoreNullResolver(), pm.SourceMember.Name));
});
class IgnoreNullResolver : IMemberValueResolver<object, object, object, object>
{
public object Resolve(object source, object destination, object sourceMember, object destinationMember, ResolutionContext context)
{
return sourceMember ?? destinationMember;
}
}
答案 2 :(得分:0)
我从@Sergey Berezovskiy
的答案中得到启发,并在主配置中对所有地图的所有成员进行了此配置:
Mapper.Initialize(cfg =>
{
cfg.ForAllMaps((obj, cnfg) => cnfg.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null)));
}
答案 3 :(得分:0)
由于我没有评论的名声,因此我将在此处添加@Sikor @sensei的答案
如果您使用的模型具有DTO的可为空的数据类型,则可以在下面使用此扩展方法来消除Automapper依赖于特定数据类型的默认值的影响。
模型示例
public class Foo {
public bool? Example { get; set; }
}
public class FooDto {
public bool Example { get; set; }
}
扩展方法:
public static TTarget MapModelProperties<TTarget, TSource>(this TTarget target, TSource source) where TTarget : class
where TSource : class
{
// Map target into the source, where the source property is null
Mapper.Initialize(cfg =>
{
cfg.CreateMap<TTarget, TSource>()
.ForAllMembers(opt => opt.Condition((src, dest, srcMember, destMember) => destMember == null));
});
Mapper.Map(target, source);
// Map the source into the target to apply the changes
Mapper.Initialize(cfg => cfg.CreateMap<TSource, TTarget>());
Mapper.Map(source, target);
return target;
}
用法
public class Foo
{
public bool? Example { get; set; }
}
public class FooDto
{
public bool Example { get; set; }
}
public void Example()
{
var foo = new Foo
{
Example = null
};
var fooDto = new FooDto
{
Example = true
};
fooDto.MapModelProperties(foo);
}
这会将Dto属性值映射到所有为null的模型的属性值。然后将模型属性值映射回Dto,从而仅更改模型中存在的Dto值。
答案 4 :(得分:0)
这可能有点晚了,但对于那些仍在寻找的人来说,这可能会解决您和我一样的问题。
我同意@sergey 使用
<块引用>CreateMap
但是将可空映射到不可空将是一个问题,例如:int?到 int 它总是会返回 0。要修复它,您可以转换为 int 吗?到 int 映射。
<块引用>CreateMap
CreateMap