web-dev-qa-db-fra.com

Automapper - Source multi-objets et une destination

J'utilise le mappeur automatique pour mapper plusieurs objets (classe db en objets ui).

Carte 1:

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

Carte 2:

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

destination d = new destination();

// Carte 1

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

// Carte 2

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

Une fois que j'appelle à la "carte 2", les valeurs remplies à l'aide de la carte 1 sont perdues. Comment puis-je réparer ça?

55
CoolArchTek

Map a une surcharge qui prend un objet source et destination:

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

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

avec la réponse acceptée comme méthodes d'extension, version simple et générale:

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

après avoir configuré le mappage pour chaque type d'entrée:

IMapper mapper = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Person, PersonCar>();
    cfg.CreateMap<Car, PersonCar>();
}).CreateMapper();
28
Grastveit
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);
8
Ramakrishna Talla

Selon moi, vous devez éviter d'appeler la méthode Map surchargée en prenant une instance de l'objet de destination comme expliqué dans la réponse acceptée. Cela ne vous permettra pas de tester/valider votre configuration de mappage (Mapper.Configuration.AssertConfigurationIsValid()) ou pour ce faire, vous ajouterez beaucoup de "Ignorer" dans vos mappages.

Une solution très simple consiste à créer un type composite contenant des références source et à définir votre mappage vers la destination en fonction de ce type composite.

Quelque chose comme:

    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();
    }
0
asidis