2

我的问题

“源”对象视图中不存在的同一类的属性用空值覆盖“目标”对象中的相同属性。我该如何防止这种情况?影响我如何确保仅填充(非空)属性合并到“目标”对象中。我也用 Automapper 尝试过,但失败了,但我很乐意使用 Automapper 解决方案作为替代方案。

我很欣赏这个“空映射”问题以前出现过,但我担心我的情况会更复杂,因为有嵌套对象。好吧,我尝试了建议的选项,但无法使它们起作用。所以我在这里。

非常感谢任何帮助。

我很欣赏这是一个复杂的问题,并且真的非常感谢任何帮助,特别是如果有人可以为我制作代码示例。这几天我把头发拉出来了:(

我尝试过的

我有 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”字段,因此我怀疑模型绑定正在为新的“MyDoc”对象上的“DataOfBirth”属性创建空值,当我调用时:

        public ActionResult Index(Document myDoc)

非常感谢,埃德。

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

2 回答 2

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);
于 2012-11-29T23:06:03.563 回答
1

这个简单AutoMapper的测试对我有用:

课程

public class Client
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

自动映射器配置

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

于 2012-11-30T02:02:48.873 回答