C# 映射忽略源对象中的所有空值属性
我正在尝试映射两个相同类型的对象。 我要做的是自动映射到igonore所有属性,这些属性在源对象中具有C# 映射忽略源对象中的所有空值属性,c#,.net,repository,automapper,C#,.net,Repository,Automapper,我正在尝试映射两个相同类型的对象。 我要做的是自动映射到igonore所有属性,这些属性在源对象中具有Null值,并在目标对象中保留现有值 我试着在我的“存储库”中使用它,但它似乎不起作用 Mapper.CreateMap<TEntity, TEntity>().ForAllMembers(p => p.Condition(c => !c.IsSourceValueNull)); Mapper.CreateMap().ForAllMembers(p=>p.Conditi
Null
值,并在目标对象中保留现有值
我试着在我的“存储库”中使用它,但它似乎不起作用
Mapper.CreateMap<TEntity, TEntity>().ForAllMembers(p => p.Condition(c => !c.IsSourceValueNull));
Mapper.CreateMap().ForAllMembers(p=>p.Condition(c=>!c.IsSourceValueNull));
有什么问题吗 到目前为止,我已经这样解决了
foreach (var propertyName in entity.GetType().GetProperties().Where(p=>!p.PropertyType.IsGenericType).Select(p=>p.Name))
{
var value = entity.GetType().GetProperty(propertyName).GetValue(entity, null);
if (value != null)
oldEntry.GetType().GetProperty(propertyName).SetValue(oldEntry, value, null);
}
但是仍然希望找到一个使用AutoMapper的解决方案,这很有趣,但是你最初的尝试应该是可行的。以下测试为绿色:
using AutoMapper;
using NUnit.Framework;
namespace Tests.UI
{
[TestFixture]
class AutomapperTests
{
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Foo { get; set; }
}
[Test]
public void TestNullIgnore()
{
Mapper.CreateMap<Person, Person>()
.ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));
var sourcePerson = new Person
{
FirstName = "Bill",
LastName = "Gates",
Foo = null
};
var destinationPerson = new Person
{
FirstName = "",
LastName = "",
Foo = 1
};
Mapper.Map(sourcePerson, destinationPerson);
Assert.That(destinationPerson,Is.Not.Null);
Assert.That(destinationPerson.Foo,Is.EqualTo(1));
}
}
}
使用AutoMapper;
使用NUnit.Framework;
命名空间测试.UI
{
[测试夹具]
类自动映射测试
{
公共阶层人士
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共int?Foo{get;set;}
}
[测试]
公共void TestNullIgnore()
{
Mapper.CreateMap()
.ForAllMembers(opt=>opt.Condition(srs=>!srs.IsSourceValueNull));
var sourcePerson=新用户
{
FirstName=“比尔”,
LastName=“盖茨”,
Foo=null
};
var destinationPerson=新用户
{
FirstName=“”,
LastName=“”,
Foo=1
};
Mapper.Map(sourcePerson,destinationPerson);
Assert.That(destinationPerson,Is.Not.Null);
断言(destinationPerson.Foo,Is.EqualTo(1));
}
}
}
将Marty的解决方案(有效)再向前推进一步,这里有一个通用方法,使其更易于使用:
public static U MapValidValues<U, T>(T source, U destination)
{
// Go through all fields of source, if a value is not null, overwrite value on destination field.
foreach (var propertyName in source.GetType().GetProperties().Where(p => !p.PropertyType.IsGenericType).Select(p => p.Name))
{
var value = source.GetType().GetProperty(propertyName).GetValue(source, null);
if (value != null && (value.GetType() != typeof(DateTime) || (value.GetType() == typeof(DateTime) && (DateTime)value != DateTime.MinValue)))
{
destination.GetType().GetProperty(propertyName).SetValue(destination, value, null);
}
}
return destination;
}
解决方法-在目标类型中添加DataMember属性[DataMember(EmitDefaultValue=false)]将在源值为null时删除该属性
[DataContract]
class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int? Age { get; set; }
[DataMember(EmitDefaultValue = false)]
public string Role { get; set; }
}
如果角色值为null,则将删除角色属性。
条件
使用3个参数重载,让我们将表达式等效于示例p.Condition(c=>!c.IsSourceValueNull)
:
方法签名:
void Condition(Func<TSource, TDestination, TMember, bool> condition
void条件(Func条件
等效表达式:
CreateMap<TSource, TDestination>.ForAllMembers(
opt => opt.Condition((src, dest, sourceMember) => sourceMember != null));
CreateMap.ForAllMembers(
opt=>opt.Condition((src、dest、sourceMember)=>sourceMember!=null));
Hi,我们可以为所有类配置条件吗?我尝试了Mapper.CreateMap
,但它不起作用(找不到类型或命名空间名称“tenty”)。谢谢。对于更高版本,答案是@nenad是正确的。您也可以检查这个答案:嗨,我们可以为所有类配置条件吗?我尝试了Mapper.CreateMap
,但它不起作用(找不到类型或命名空间名称“tenty”)。谢谢。可能存在重复的
CreateMap<TSource, TDestination>.ForAllMembers(
opt => opt.Condition((src, dest, sourceMember) => sourceMember != null));