我的问题
“Source”对象View中不存在的同一个类的属性将使用null覆盖“Target”对象中的相同属性。我该如何防止这种情况?在影响中,我如何确保仅将填充(非空)属性合并到“目标”对象中。我也尝试使用Automapper,但失败了,但我很乐意将Automapper解决方案作为替代方案。
我很欣赏这个“Null Mapping”问题之前出现过,但我担心由于存在嵌套对象,我的情况更加复杂。好吧,我尝试了建议的选项,我无法让它们工作。我在这里。
非常感谢任何帮助。
我很欣赏这是一个复杂的问题,真的,非常感谢任何帮助,特别是如果有人可以为我生成代码示例。我已经把头发拉过来几天了:(
我的尝试
我有2个对象,一个是原始对象(“目标”),一个(“源”)由一个表单填充,即一个视图。
原始“目标”对象(myOrigDoc)如下所示:
表单“源”对象(myDoc)如下所示:
然后我做了映射:
myOrigDoc.Introduction.InjectFrom<StrNotNull>(myDoc.Introduction);
使用以下注射器:
public class StrNotNull: ConventionInjection
{
bool blnNotNull = false;
bool blnMatch = false;
protected override bool Match(ConventionInfo c)
{
blnNotNull = false;
blnMatch = false;
//if ((c.SourceProp.Type == typeof(string)) && (c.SourceProp.Value != null))
// blnAssignable = true;
if (c.SourceProp.Value != null)
blnNotNull = true;
if ((c.SourceProp.Name == c.TargetProp.Name) && (blnNotNull))
blnMatch = true;
return blnMatch;
}
}
我最终得到了:
表单上没有“DateOfBirth”字段,因此我怀疑Model Binding在新的“MyDoc”对象上为“DataOfBirth”属性创建一个空值,当我调用时:
public ActionResult Index(Document myDoc)
非常感谢,Ed。
EDIT1:我认为这是由于子类而导致的嵌套映射问题。不确定我如何在ValueInjector中对此进行排序。
EDIT2:来自嵌套映射文档的可能的Automapper解决方案,但我无法使其工作。我仍然将我的空值传递到目标。:
Mapper.CreateMap<XSD_Smart2.Document, XSD_Smart2.Document>
().ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));
Mapper.CreateMap<XSD_Smart2.DocumentIntroduction, XSD_Smart2.DocumentIntroduction>
().ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));
Mapper.CreateMap<XSD_Smart2.Client, XSD_Smart2.Client>().ForAllMembers(opt =>
opt.Condition(srs => !srs.IsSourceValueNull));
答案 0 :(得分:3)
更新ValueInjecter 3
public class IgnoreNulls : LoopInjection
{
protected override void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
{
var val = sp.GetValue(source);
if (val != null)
{
tp.SetValue(target, val);
}
}
}
以前的版本
创建一个具有此行为的自定义注入:
public class IgnoreNulls : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == c.TargetProp.Name
&& c.SourceProp.Value != null;
}
}
并使用它:
target.InjectFrom<IgnoreNulls>(source);
答案 1 :(得分:1)
这个简单的AutoMapper
测试对我有用:
<强>类强>
public class Client
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
<强> AutoMapperConfiguration 强>
public class MyProfile : Profile
{
protected override void Configure()
{
CreateMap<Client, Client>()
.ForAllMembers(opt => opt.Condition(src => !src.IsSourceValueNull));
}
}
单元测试
[TestFixture]
public class MappingTests
{
[Test]
public void AutoMapper_Configuration_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
}
[Test]
public void AutoMapper_ClientMapping_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
var source = new Client
{
FirstName = "SourceFirstName1",
LastName = null
};
var destination = new Client
{
FirstName = "DestinationFirstName1",
LastName = "DestinationLastName1"
};
destination = Mapper.Map(source, destination);
Assert.That(destination, Is.Not.Null);
Assert.That(destination.FirstName, Is.EqualTo("SourceFirstName1"));
Assert.That(destination.LastName, Is.EqualTo("DestinationLastName1"));
}
}
<强>更新强>
有趣的是,当您使用此映射来映射列表时,它会失败。 IE - 此测试失败:
[Test]
public void AutoMapper_ClientListMapping_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
var source = new List<Client>
{
new Client
{
FirstName = "SourceFirstName1",
LastName = null
},
new Client
{
FirstName = null,
LastName = "SourceLastName2"
}
};
var destination = new List<Client>
{
new Client
{
FirstName = "DestinationFirstName1",
LastName = "DestinationLastName1"
},
new Client
{
FirstName = "DestinationFirstName2",
LastName = "DestinationLastName2"
}
};
destination = Mapper.Map(source, destination);
Assert.That(destination, Is.Not.Null);
Assert.That(destination.Count, Is.EqualTo(2));
Assert.That(destination[0].FirstName, Is.EqualTo("SourceFirstName1"));
Assert.That(destination[0].LastName, Is.EqualTo("DestinationLastName1"));
// /\ Line above went BANG! /\
Assert.That(destination[1].FirstName, Is.EqualTo("DestinationFirstName2"));
Assert.That(destination[1].LastName, Is.EqualTo("SourceLastName2"));
}
这看起来像是AutoMapper中的一个错误(在2.2.0和2.2.1-ci9000中)