20

Automapperを使用して複数のDTOオブジェクトを単一のViewModelオブジェクトにマップできるかどうか疑問に思いましたか?

基本的に、複数のDTOオブジェクトがあり、ASP.NETMVC2.0の単一の画面にそれぞれの情報を表示したいと考えています。そのために、DTOオブジェクト(またはそれらの一部...)をViewmodelにフラット化し、そのビューモデルをビューに渡します。1つのDTOがあればこれは簡単ですが、複数のDTOで行われるのを見たことがありません。明らかに、これを行うには(オートマッパー以外で)いくつかの回り道がありますが、これは可能であれば私が採用したいアプローチです。

4

6 に答える 6

14

クエリに関する次のリンクを確認してください

http://consultingblogs.emc.com/owainwragg/archive/2010/12/22/automapper-mapping-from-multiple-objects.aspx

于 2012-01-19T08:31:48.913 に答える
10

2つ以上のDTOオブジェクトを保持する複合DTOを作成し、複合DTOを出力ビューモデルにマップできます。

于 2010-01-24T16:34:41.837 に答える
9

2つのDTOクラスと1つのフラット化されたビューモデルがある場合:

public class Dto1
{
    public string Property1 { get; set; }
}
public class Dto2
{
    public string Property2 { get; set; }
}
public class FlattenedViewModel
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

そして、モデルを表示するために両方のDTOのマッピングを作成します。

CreateMap<Dto1, FlattenedViewModel>();
CreateMap<Dto2, FlattenedViewModel>();

1番目のDTOをモデルにマップしてから、2番目のDTOを「追加」することができます。

var dto1 = new Dto1 { Property1 = "Value1"; }
var dto2 = new Dto2 { Property2 = "Value2"; }

var model = Mapper.Map<FlattenedViewModel>(dto1); // map dto1 properties
Mapper.Map(dto2, model); // append dto2 properties
于 2015-05-21T10:49:42.743 に答える
4

params配列を受け取るIMappingEngineからマップオーバーライド拡張メソッドを追加できます。何かのようなもの:

public static class AutoMapperExtensions
{
    public static T Map<T>(this IMappingEngine engine, params object[] sources) where T : class
    {
        if (sources == null || sources.Length == 0)
            return default(T);

        var destinationType = typeof (T);
        var result = engine.Map(sources[0], sources[0].GetType(), destinationType) as T;
        for (int i = 1; i < sources.Length; i++)
        {
            engine.Map(sources[i], result, sources[i].GetType(), destinationType);
        }

        return result;
    }
}

次に、次のように呼び出すことができます。

var result = Mapper.Engine.Map<MyViewModel>(dto1, dto2, dto3);
于 2012-11-14T15:51:11.177 に答える
1

これは、この回答の期限切れのリンクからの情報です:https ://stackoverflow.com/a/8923063/2005596

AutoMapper(http://automapper.codeplex.com)を使用する場合、複数のエンティティを1つのエンティティにマップする必要があるシナリオがよくあります。通常、これは、多数のドメインエンティティから単一のビューモデル(ASP.NET MVC)にマッピングするときに発生します。残念ながら、AutoMapper APIは、複数のエンティティを1つのエンティティにマップする機能を公開していません。ただし、これを行うためのヘルパーメソッドを作成するのは比較的簡単です。以下に、私が取ったアプローチを説明します。

この例では、ドメインモデルに次のエンティティがあります

public class Person

{

    public int Id { get; set; }



    public string Firstname { get; set; }



    public string Surname { get; set; }

}



public class Address

{

    public int Id { get; set; }



    public string AddressLine1 { get; set; }



    public string AddressLine2 { get; set; }



    public string Country { get; set; }

}



public class Comment

{

    public string Text { get; set; }



    public DateTime Created { get; set; }

}

これに加えて、(ASP.NET MVCを使用して)1つのページにその人の詳細をその人の住所と関連するコメントを表示する必要があります。これを実装するために、以下に示すビューモデルを作成しました。これには、上記の3つのドメインエンティティすべてからのデータが含まれています。

public class PersonViewModel

{

    public int Id { get; set; }



    [DisplayName("Firstname")]

    public string Firstname { get; set; }



    [DisplayName("Surname")]

    public string Surname { get; set; }



    [DisplayName("Address Line 1")]

    public string AddressLine1 { get; set; }



    [DisplayName("Address Line 2")]

    public string AddressLine2 { get; set; }



    [DisplayName("Country Of Residence")]

    public string Country { get; set; }



    [DisplayName("Admin Comment")]

    public string Comment { get; set; }



}

コントローラアクションメソッドでは、必要なエンティティを取得するためにドメインレイヤーに3つの個別の呼び出しを行いますが、これでも、複数のソースエンティティを単一の宛先エンティティにマップする必要があるという問題が残ります。このマッピングを実行するために、AutoMapperをカプセル化し、複数のソースオブジェクトを1つの宛先オブジェクトにマッピングできる機能を公開するヘルパークラスを作成しました。このクラスを以下に示します

public static class EntityMapper

{

    public static T Map<T>(params object[] sources) where T : class

    {

        if (!sources.Any())

        {

            return default(T);

        }



        var initialSource = sources[0];



        var mappingResult = Map<T>(initialSource);



        // Now map the remaining source objects

        if (sources.Count() > 1)

        {

            Map(mappingResult, sources.Skip(1).ToArray());

        }



        return mappingResult;

    }



    private static void Map(object destination, params object[] sources)

    {

        if (!sources.Any())

        {

            return;

        }



        var destinationType = destination.GetType();



        foreach (var source in sources)

        {

            var sourceType = source.GetType();

            Mapper.Map(source, destination, sourceType, destinationType);

        }

    }



    private static T Map<T>(object source) where T : class

    {

        var destinationType = typeof(T);

        var sourceType = source.GetType();



        var mappingResult = Mapper.Map(source, sourceType, destinationType);



        return mappingResult as T;

    }

}

複数のソースオブジェクトを1つの宛先にマップするために、AutoMapperが提供する機能を利用して、ソースオブジェクトと既存の宛先オブジェクトの間のマッピングを実行できるようにしました。

最後に、3つのエンティティを取得し、単一のビューモデルへのマッピングを実行するコントローラーからのコードを以下に示します。

    public ActionResult Index()

    {



        // Retrieve the person, address and comment entities and

        // map them on to a person view model entity

        var personId = 23;



        var person = _personTasks.GetPerson(personId);

        var address = _personTasks.GetAddress(personId);

        var comment = _personTasks.GetComment(personId);



        var personViewModel = EntityMapper.Map<PersonViewModel>(person, address, comment);



        return this.View(personViewModel);

    }
于 2019-04-11T20:01:06.840 に答える
0

私はこれを自分で解決し、素晴らしい解決策を持っています。2つのビューが実際にシステム内で何らかの形で関連している可能性があります(特にEntity Frameworkを使用している場合)。モデルを確認すると、関係を表示するものが表示されるはずです。追加しない場合は、それを追加するだけです。(virtual

あなたのモデル

    public class Dto1
    {
        public int id { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
        public string Property4 { get; set; }
        public string Property5 { get; set; }

        public virtual Dto2 dto2{ get; set; }

    }

    public class Dto2
    {
        public int id { get; set; }
        public string PropertyB { get; set; }
        public string PropertyC { get; set; }
        public string PropertyD { get; set; }
        public string PropertyE { get; set; }
    }

あなたのViewModels

    public class Dto1ViewModel
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }

        public virtual Dto2VMForDto1 dto2{ get; set; }
    }

//Special ViewModel just for sliding into the above
    public class Dto2VMForDto1 
    {
        public int id { get; set; }
        public string PropertyB { get; set; }
        public string PropertyC { get; set; }
    }

Automapperは次のようになります。

        cfg.CreateMap< Dto1, Dto1ViewModel>();
        cfg.CreateMap< Dto2, Dto2VMForDto1 >();

LinQを使用してデータを取得していると仮定します。

Dto1ViewModel thePageVM = (from entry in context.Dto1 where...).ProjectTo<Dto1ViewModel>();

ビオラ、すべてがうまくいくでしょう。あなたの見解では、を使用してアクセスするだけですmodel.dto2.PropertyB

于 2016-07-08T02:03:36.713 に答える