2011-12-02 20 views
13

È possibile assegnare proprietà a setter privati ​​utilizzando AutoMapper?Proprietà mappatura AutoMapper con private setter

+0

Quale versione di Automapper stai usando? Hai provato a farlo? – PatrickSteele

+8

@blockhead in realtà è una questione molto importante, gli oggetti immutabili sono una pratica architettonica molto migliore degli oggetti che possono essere cambiati a piacimento (esponendo pubblicamente i loro setter). Questa è la ragione esatta per cui Entity Framework ha recentemente aggiunto la capacità di idratarsi in proprietà private, per consentire al modello di dominio di rimanere immutabile dopo l'idratazione iniziale. Forse non è il leozilla che ha bisogno di rispolverare la loro architettura. ;) – Marchy

+0

Mi scusi? Le proprietà private dovrebbero essere private. Sono i dati che appartengono all'oggetto e solo l'oggetto lo sa e dovrebbe sapere di quei dati. – blockhead

risposta

15

Se si imposta il valore di questa proprietà nel costruttore come questo

public class RestrictedName 
{ 
    public RestrictedName(string name) 
    { 
     Name = name; 
    } 

    public string Name { get; private set; } 
} 

public class OpenName 
{ 
    public string Name { get; set; } 
} 

quindi è possibile utilizzare ConstructUsing come questo

Mapper.CreateMap<OpenName, RestrictedName>() 
      .ConstructUsing(s => new RestrictedName(s.Name)); 

che funziona con questo codice

var openName = new OpenName {Name = "a"}; 
var restrictedName = Mapper.Map<OpenName, RestrictedName>(openName); 
Assert.AreEqual(openName.Name, restrictedName.Name); 
+2

Questo non sembra essere richiesto con l'ultima versione. Sono in grado di mappare classi con privati ​​setter. Deve usare la riflessione internamente. – Monstieur

+0

@Locutus Forse potresti trasformare quel commento in una risposta? Probabilmente dovrebbe essere contrassegnato come la nuova risposta a questa domanda. – julealgon

9

AutoMapper consente ora (non sono sicuro, da quando) di mappare le proprietà con i setter privati. Sta usando la riflessione per creare oggetti.

classi Esempio:

public class Person 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
} 


public class PersonDto 
{ 
    public string Fullname { get; private set; } 
} 

e mappatura:

AutoMapper.Mapper.CreateMap<Person, PersonDto>() 
    .ForMember(dest => dest.Fullname, conf => conf.MapFrom(src => src.Name + " " + src.Surname)); 

var p = new Person() 
{ 
    Name = "John", 
    Surname = "Doe" 
}; 

var pDto = AutoMapper.Mapper.Map<PersonDto>(p); 

automapper mapperà proprietà con setter privata senza alcun problema. Se si desidera forzare l'incapsulamento, è necessario utilizzare IgnoreAllPropertiesWithAnInaccessibleSetter. Con questa opzione, tutte le proprietà private (e altre inaccessibili) saranno ignorate.

AutoMapper.Mapper.CreateMap<Person, PersonDto>() 
    .ForMember(dest => dest.Fullname, conf => conf.MapFrom(src => src.Name + " " + src.Surname)) 
    .IgnoreAllPropertiesWithAnInaccessibleSetter(); 

Il problema emergerà, se si utilizzerà Silverlight. Secondo MSDN: https://msdn.microsoft.com/en-us/library/stfy7tfc(v=VS.95).aspx

In Silverlight, you cannot use reflection to access private types and members. 
3

Vedi #600 Private/internal destination properties.

Soluzione:

public class PrivateInternalProfile { 
    protected override Configure() { 
     ShouldMapField = fieldInfo => true; 
     ShouldMapProperty = propertyInfo => true; 
     CreateMap<User, UserDto>(); //etc 
    } 
} 
Problemi correlati