簡體   English   中英

Automapper - 多對象源和一個目標

[英]Automapper - Multi object source and one destination

我正在使用自動映射器來映射多個對象(db 類到 ui 對象)。

地圖1:

Mapper.CreateMap<sourceone, destination>().ForMember(sss => sss.one, m => m.MapFrom(source => source.abc));

地圖2:

Mapper.CreateMap<sourcetwo, destination>().ForMember(sss => sss.two, m => m.MapFrom(source => source.xyz));

destination d = new destination();

//地圖1

d = AutoMapper.Mapper.Map<sourceone, destination>(sourceone);

//地圖2

d = AutoMapper.Mapper.Map<sourcetwo, destination>(sourcetwo);

一旦我調用“地圖 2”,使用地圖 1 填充的值就會丟失..(即destination.one 變為空)。 我該如何解決?

Map有一個帶有源和目標對象的重載:

d = AutoMapper.Mapper.Map<sourceone, destination>(sourceone);

/* Pass the created destination to the second map call: */
AutoMapper.Mapper.Map<sourcetwo, destination>(sourcetwo, d);
mapper.MergeInto<PersonCar>(person, car)

將接受的答案作為擴展方法,簡單和通用版本:

public static TResult MergeInto<TResult>(this IMapper mapper, object item1, object item2)
{
    return mapper.Map(item2, mapper.Map<TResult>(item1));
}

public static TResult MergeInto<TResult>(this IMapper mapper, params object[] objects)
{
    var res = mapper.Map<TResult>(objects.First());
    return objects.Skip(1).Aggregate(res, (r, obj) => mapper.Map(obj, r));
}

為每個輸入類型配置映射后:

IMapper mapper = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Person, PersonCar>();
    cfg.CreateMap<Car, PersonCar>();
}).CreateMapper();
public class Person
{
    public string Name { get; set; }
    public string PhNo { get; set; }
}
public class Company
{
    public int EmpNo { get; set; }
    public string Title { get; set; }
}

public class PersonCompany
{
    public string Name { get; set; }
    public string PhNo { get; set; }

    public int EmpNo { get; set; }
    public string Title { get; set; }
}

//you can test as below
        var pMap = Mapper.CreateMap<Person,PersonCompany>();
        pMap.ForAllMembers(d => d.Ignore()); 
        pMap.ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name))
            .ForMember(d => d.PhNo, opt => opt.MapFrom(s => s.PhNo));

        var cMap = Mapper.CreateMap<Company, PersonCompany>();
        cMap.ForAllMembers(d => d.Ignore());
        cMap.ForMember(d => d.EmpNo, opt => opt.MapFrom(s => s.EmpNo))
            .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Title));


        var person = new Person { Name = "PersonName", PhNo = "212-000-0000" };
        var personCompany = Mapper.Map<Person,PersonCompany>(person);
        var company = new Company { Title = "Associate Director", EmpNo = 10001 };
        personCompany = Mapper.Map(company, personCompany);

        Console.WriteLine("personCompany.Name={0}", personCompany.Name);
        Console.WriteLine("personCompany.PhNo={0}", personCompany.PhNo);
        Console.WriteLine("personCompany.EmpNo={0}", personCompany.EmpNo);
        Console.WriteLine("personCompany.Title={0}", personCompany.Title);

根據我的說法,您應該避免調用重載的 Map 方法來獲取目標對象的實例,如已接受的答案中所述。 這不會讓您測試/驗證您的映射配置( Mapper.Configuration.AssertConfigurationIsValid() ),否則您將在映射中添加很多“忽略”。

一個非常簡單的解決方案是創建一個包含源引用的復合類型,並根據該復合類型定義到目標的映射。

就像是:

    public class SourceOneTwo
    {
        public SourceOne SourceOne { get; set; }
        public SourceTwo SourceTwo { get; set; }
    }
    static void Main(string[] args)
    {
        var config = new MapperConfiguration(cfg => 
            cfg.CreateMap<SourceOneTwo, Destination>()
            .ForMember(dest => dest.one, m => m.MapFrom(source => source.SourceOne.abc))
            .ForMember(dest => dest.two, m => m.MapFrom(source => source.SourceTwo.xyz)));
        config.AssertConfigurationIsValid();
    }

現在看起來是這樣的:

DestinationDto = _mapper.Map(source2, _mapper.Map<source1type, destinationType>(source1));

只是想補充一點,現在您可以使用元組語法來定義多種類型的映射。

// configuring
Mapper
  .CreateMap<(SourceType1 Source1, SourceType2 Source2), DestinationType>()
    .ForMember(sss => sss.one, m => m.MapFrom(source => source.Source1.abc))
    .ForMember(sss => sss.two, m => m.MapFrom(source => source.Source2.xyz));

// using
var result = Mapper.Map<DestinationType>((source1, source2));

優點:

  • 從第一種映射后不必記住從第二種映射
  • 所有映射都是一次在一個地方定義的(只要您不需要單獨的映射以及組合的映射)
  • 從 2 種以上的源類型映射時不那么麻煩
  • 本質上是@asidis 的想法,但不需要單獨的類型

缺點:

  • 好吧,與一般的 Automapper 一樣,您必須知道在哪里查找,以找出用於映射的類型
  • 當涉及多種類型時,可能看起來有點笨拙

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM