2010-11-17 16 views
17

Al momento ho il seguente mappatura:Automapper insieme Dependency Injection

Mapper.CreateMap<Journal, JournalDto>(); 

Ora, Journal contiene un membro denominato RefTypeID, che esiste valore corrispondente in un'altra tabella del database; per cercare questo valore, ho un servizio che gestisce una semplice richiesta int -> string. La configurazione dell'automa- tore automatico si trova attualmente in una classe statica all'inizio del programma. Va bene spostare il codice di mappatura in una classe che viene iniettata nel mio contenitore DI o esiste un modo migliore?

+0

L'unica ragione per cui non posso pensare sarebbe puramente organizzativa. Potresti avere un codice di mappatura su tutti i tuoi progetti. Se il tuo oggetto dominio cambia o dtos potrebbe non essere l'ideale. Ma sono curioso di scoprire dalle altre persone le loro opinioni. – Daniel

+0

Bene, manterrei comunque il codice di mappatura in un unico posto, ad es.quella classe, che prenderebbe tutti i servizi necessari dal contenitore DI. Devo solo inizializzare la mappatura da solo invece di poter fare affidamento sul costruttore statico eseguendolo automaticamente. – Femaref

+0

Per l'ultima versione, dai un'occhiata a [questo] (http://stackoverflow.com/a/35431096/1977871) quindi rispondi allo – VivekDev

risposta

8

Ecco come ho risolto:

ho definito un IMappingCreator interfaccia:

public interface IMappingCreator 
{ 
    void CreateMappings(); 
} 

sono andato avanti e implementato una classe con tale interfaccia (sto usando MEF come contenitore DI, è lì gli attributi vengono Provenendo dalla) che è messo nel contenitore dI come IMappingCreator:

[Export(typeof(IMappingCreator))] 
    public class Mapping : IMappingCreator 
    { 
     private readonly IRefTypesLookup iRefTypesLookup; 


     [ImportingConstructor] 
     public Mapping(IRefTypesLookup rtl) 
     { 
      iRefTypesLookup = rtl; 
     } 

     public void CreateMappings() 
     { 
      Mapper.CreateMap<Journal, DisplayJournal>().AfterMap((j, dj) => dj.RefTypeName = iRefTypesLookup.Lookup(j.RefTypeID)); 
     } 
    } 

Infine, a mio avvio dell'applicazione, vado a prendere tutte Instan ES di tale interfaccia nel contenitore e chiamare il metodo CreateMappings su di loro:

var mappings = container.GetExportedValues<IMappingCreator>(); 

    foreach (IMappingCreator mc in mappings) 
    { 
     mc.CreateMappings(); 
    } 

Questo rende la configurazione iniziale abbastanza facile, come tutta la creazione avviene in un unico luogo, e si può avere il maggior numero di creatori di mappatura come si desidera (tuttavia, è necessario mantenerli al minimo, magari una volta per progetto o giù di lì, afferrando tutti i servizi necessari per mappare i tipi specifici in quel progetto).

+0

Questo è abbastanza bello ... potrei dover prendere a prestito da questo! : D MEF è una grande aggiunta al framework. – Daniel

+0

sentitevi liberi di, non penso di essere l'unico a scontrarmi con questo problema. – Femaref

14

Un modo migliore è quello di utilizzare un resolver cliente. configurazione della mappatura è destinato ad essere statico, in modo resolver personalizzati hanno lo scopo di fornire la mappatura per un singolo membro:

Mapper.Initialize(cfg => { 
    cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type)); 

    cfg.CreateMap<Journal, DisplayJournal>() 
     .ForMember(dest => dest.RefTypeName, 
      opt => opt.ResolveUsing<RefTypeNameResolver>()); 
}); 

Allora il tuo resolver diventa:

[Export(typeof(IRefTypeNameResolver))] 
public class RefTypeNameResolver : ValueResolver<Journal, string>, IRefTypeNameResolver 
{ 
    private readonly IRefTypesLookup iRefTypesLookup; 

    [ImportingConstructor] 
    public RefTypeNameResolver (IRefTypesLookup rtl) 
    { 
     iRefTypesLookup = rtl; 
    } 

    protected override string ResolveCore(Journal source) 
    { 
     return iRefTypesLookup.Lookup(source.RefTypeID); 
    } 
} 

configurazione ha bisogno per eseguire una volta, che è il motivo per cui la API di configurazione fornisce agganci nella API esecuzione (convertitori di tipi, resolver valore etc.)

+1

Sapevo di ValueResolver, ma pensavo che fossero inutili perché mi mancava la configurazione ConstructServicesUsing. Ben fatto! – Kugel

Problemi correlati