2017-01-26 3 views
1

Also ich habe eine Schnittstelle, die für DI:AutoMapper Nested Mappings

public interface IMapper<in TIn, out TOut> 
{ 
    TOut Map(TIn objectToMap); 
} 

Und eine Basisklasse für meinen Mapper:

public abstract class MapperBase<TIn, TOut> : IMapper<TIn, TOut> 
{ 
    internal IConfigurationProvider MapperConfiguration { get; set; } 

    public TOut Map(TIn objectToMap) 
    { 
     return MapperConfiguration.CreateMapper().Map<TOut>(objectToMap); 
    } 
} 

Und ich werde das folgende vereinfachte Datenmodell verwenden (“ same“für DAL und Service-Layer)

public class Client 
{ 
    public int Id { get; set; } 
    public List<Contract> Contracts { get; set; } 
} 

public class Contract 
{ 
    public int Id { get; set; } 
    public List<Installation> Installations { get; set; } 
} 

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

ich folgenden Mapper zwischen meiner DAL und Service-Schicht habe:

Aber wenn ich einen Client abdecke, gibt AutoMapper eine Ausnahme, die besagt, dass für die Installation kein Mapping definiert ist (der verschachtelte Typ).

Wenn ich ein Mapping für die Installation in der Client Mapper konfigurieren, funktioniert es gut.

Was ich nicht verstehe ist, ich biete eine spezifische Methode, um den verschachtelten Typ "Contract" von "Client" abzubilden, und eine spezifische Karte "Installation" von "Contract", also warum versucht Autoadapter zu verwenden seine Mapping-Konfiguration für die verschachtelten Typen der verschachtelten Typen? Warum hält er nicht einfach dort an und benutzt die Methode, die ich zur Verfügung gestellt habe? Wie kann ich erreichen, was ich hier machen will, Mapper verketten?

Antwort

0

Ich habe eine Lösung mit dem Profil gefunden.

ich all meine Zuordnungen in einer Klasse definieren, die vom Profil ableitet:

public class DalToServiceProfile : Profile 
{ 
    protected override void Configure() 
    { 
     CreateMap<DAL.Client, Interface.Model.Client>(); 
     CreateMap<DAL.Installation, Interface.Model.Installation>(); 
     CreateMap<DAL.Contract, Interface.Model.Contract>(); 
    } 
} 

ich meine Basisklasse wie diese Aussehen ändern:

public abstract class MapperBase<TIn, TOut, TProfile> : IMapper<TIn, TOut> where TProfile : Profile, new() 
{ 
    internal IConfigurationProvider MapperConfiguration { get; set; } 

    protected MapperBase() 
    { 
     MapperConfiguration = new MapperConfiguration(cfg => 
     { 
      cfg.AddProfile<TProfile>(); 
     }); 
    } 

    public TOut Map(TIn objectToMap) 
    { 
     return MapperConfiguration.CreateMapper().Map<TOut>(objectToMap); 
    } 
} 

Und mein Mapper ar jetzt einfacher:

public class DalClientToServiceMapper : MapperBase<DAL.Client, Interface.Model.Client, DalToServiceProfile> 
{ 
} 

public class DalContractToServiceMapper : MapperBase<DAL.Contract, Interface.Model.Contract, DalToServiceProfile> 
{ 
} 

public class DalInstallationToServiceMapper : MapperBase<DAL.Installation, Interface.Model.Installation, DalToServiceProfile> 
{ 
} 

Ich brauche diese zusätzliche Schicht, da wir Abhängigkeitsinjektion verwenden und die Mapper basierend auf injizieren müssen ihre Schnittstelle.

Alle meine Mapper kennen die Mapping-Konfiguration, aber das sehe ich in meiner Situation nicht als eine große Sache an.

Auch sie sind nicht verkettet, aber da sie jeweils nur das gleiche Profil laden, machen sie das gleiche Zeug.

In der Tat ist alles, was ich hier tun ist die Entkoppelung meiner Mapper mit dem IMapper-Schnittstelle, so dass ich einfach meine Mapper injizieren und sie stark typisiert verwenden kann. Cleaner ruft dann überall in meinen Diensten Mapper.Map auf oder erstellt Mapper in meinen Service-Fassaden.