2

私の問題

ビューに存在しない同じクラスの「ソース」オブジェクトプロパティは、「ターゲット」オブジェクトの同じプロパティをnullで上書きしています。これを防ぐにはどうすればよいですか?影響を受けるのは、入力された(nullではない)プロパティのみが「ターゲット」オブジェクトにマージされるようにする方法です。Automapperでもこれを試しましたが失敗しましたが、代わりにAutomapperソリューションを使用できれば幸いです。

この「ヌルマッピング」の質問が以前に出てきたことはありがたいですが、ネストされたオブジェクトがあるため、私の状況がより複雑になるのではないかと心配しています。提案されたオプションを試してみましたが、機能させることができませんでした。だからここにいます。

助けてくれてありがとう。

これは複雑な問題であり、特に誰かが私のためにコードサンプルを作成できる場合は、これに関する支援に本当に感謝しています。私は数日間これの上に髪を引っ張っています:(

私が試みたこと

2つのオブジェクトがあります。1つはoriginal( "Target")で、もう1つ( "Source")はフォーム(ビュー)によって入力されます。

元の「ターゲット」オブジェクト(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」プロパティにnull値を作成していると思われます。

        public ActionResult Index(Document myDoc)

どうもありがとう、エド。

編集1:これはサブクラスによるネストされたマッピングの問題だと思います。ValueInjectorでこれをどのようにソートするかわかりません。

EDIT2 :ネストされたマッピングのドキュメントから可能なオートマッパーソリューションですが、動作させることができませんでした。私はまだ自分のヌルをターゲットに渡しています。

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

ValueInjecter3の更新

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; }
}

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)

于 2012-11-30T02:02:48.873 に答える