2010-02-10 15 views

risposta

113

Usa ConstructUsing

questo vi permetterà di specificare quali il costruttore da utilizzare durante la mappatura. ma poi tutte le altre proprietà verranno automaticamente mappate in base alle convenzioni.

Si noti inoltre che questo è diverso da ConvertUsing in quella conversione utilizzando non continuerà a mappare tramite le convenzioni, ma ti darà invece il pieno controllo della mappatura.

Mapper.CreateMap<ObjectFrom, ObjectTo>() 
    .ConstructUsing(x => new ObjectTo(arg0, arg1, etc)); 

...

using AutoMapper; 
using NUnit.Framework; 

namespace UnitTests 
{ 
    [TestFixture] 
    public class Tester 
    { 
     [Test] 
     public void Test_ConstructUsing() 
     { 
      Mapper.CreateMap<ObjectFrom, ObjectTo>() 
       .ConstructUsing(x => new ObjectTo(x.Name)); 

      var from = new ObjectFrom { Name = "Jon", Age = 25 }; 

      ObjectTo to = Mapper.Map<ObjectFrom, ObjectTo>(from); 

      Assert.That(to.Name, Is.EqualTo(from.Name)); 
      Assert.That(to.Age, Is.EqualTo(from.Age)); 
     } 
    } 

    public class ObjectFrom 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 

    public class ObjectTo 
    { 
     private readonly string _name; 

     public ObjectTo(string name) 
     { 
      _name = name; 
     } 

     public string Name 
     { 
      get { return _name; } 
     } 

     public int Age { get; set; } 
    } 
} 
+0

Suppongo che "ConstructUsing" debba essere in una versione più recente di automapper rispetto a stai usando. Grazie Jon – jlembke

+6

Mille grazie per questo esempio Jon. "ConstructUsing" è fantastico! Mi consente di mantenere immutabili i miei DTO con i setter contrassegnati come privati. – Daniel

+3

Per me è un piacere; Al momento AutoMapper non apprezza i costruttori in cui tutti i parametri sono opzionali, quindi uso semplicemente .ConstructUsing (x => new MyClass()); –

7

Si dovrebbe utilizzare il metodo Map che consente di impostare la destinazione. Per esempio:

Mapper.CreateMap<ObjectFrom, ObjectTo>() 

var from = new ObjectFrom { Name = "Jon", Age = 25 }; 

var to = Mapper.Map(from, new ObjectTo(param1)); 
0

Al momento della stesura di questa risposta, automapper farà automaticamente (con una semplice chiamata CreateMap<>()) per voi se le proprietà corrispondono ai parametri del costruttore. Ovviamente, se le cose non coincidono, usare .ConstructUsing(...) è la strada da percorrere.

public class PersonViewModel 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 
} 

public class Person 
{ 
    public Person (int id, string name) 
    { 
     Id = id; 
     Name = name; 
    } 

    public int Id { get; } 

    public string Name { get; } 
} 

public class PersonProfile : Profile 
{ 
    public PersonProfile() 
    { 
     CreateMap<PersonProfile, Person>(); 
    } 
} 

Nota: Questo assume che si sta utilizzando Profiles di impostare le vostre mappature automapper.

Quando viene utilizzato come qui di seguito, questo produce l'oggetto corretto:

var model = new PersonModel 
{ 
    Id = 1 
    Name = "John Smith" 
} 

// will correctly call the (id, name) constructor of Person 
_mapper.Map<Person>(model); 

Si può leggere di più sulla costruzione automapper nella ufficiale wiki on GitHub

2

La pratica migliore è quella di utilizzare approcci documentati da automapper https://github.com/AutoMapper/AutoMapper/wiki/Construction

public class SourceDto 
{ 
     public SourceDto(int valueParamSomeOtherName) 
     { 
      Value = valueParamSomeOtherName; 
     } 

     public int Value { get; } 
} 

Mapper.Initialize(cfg => cfg.CreateMap<Source, SourceDto>().ForCtorParam("valueParamSomeOtherName", opt => opt.MapFrom(src => src.Value))); 
Problemi correlati