2010-11-17 22 views
17

I actualmente tiene el siguiente mapeo:AutoMapper junto con la inyección de dependencias

Mapper.CreateMap<Journal, JournalDto>(); 

Ahora, Journal contiene un miembro llamado RefTypeID, que existe valor correspondiente en otra tabla en la base de datos; para buscar este valor, tengo un servicio que maneja una simple solicitud int -> string. La configuración de Automapper actualmente ocurre en una clase estática al comienzo del programa. ¿Está bien mover el código de mapeo a una clase que se inyecta en mi contenedor DI o hay una forma mejor?

+0

La única razón por la que puedo pensar que no sería puramente organizativo. Posiblemente tendrá un código de mapeo en todo su proyecto (s). Si su objeto de dominio cambia o dtos podría ser menos que ideal. Pero tengo curiosidad por saber de otras personas sus opiniones. – Daniel

+0

Bueno, aún mantendría el código de mapeo en un solo lugar, es decir.esa clase, que tomaría todos los servicios necesarios del contenedor DI. Solo tengo que inicializar el mapeo yo mismo en lugar de poder confiar en el constructor estático ejecutándolo automáticamente. – Femaref

+0

Para la versión más reciente, échele un vistazo a [this] (http://stackoverflow.com/a/35431096/1977871) así que responda – VivekDev

Respuesta

8

Aquí es cómo lo resolví:

que define una interfaz IMappingCreator:

public interface IMappingCreator 
{ 
    void CreateMappings(); 
} 

que siguió adelante e implementado una clase con esa interfaz (estoy usando MEF como contenedor de DI, que es donde los atributos se Viniendo de) que se pone en el contenedor DI como 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)); 
     } 
    } 

por último, en mi inicio de la aplicación, voy a buscar todas instanc ES de esa interfaz en el contenedor y llamar al método CreateMappings en ellos:

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

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

Esto hace que la configuración inicial bastante fácil, ya que toda la creación ocurre en un solo lugar, y usted puede tener tantos creadores de mapeo como desee (sin embargo, debe mantener esos valores al mínimo, tal vez una vez por proyecto, y obtener todos los servicios necesarios para mapear los tipos específicos en ese proyecto).

+0

Esto es bastante agradable ... ¡Debo tomar prestado de esto! : D MEF es una gran adición al marco. – Daniel

+0

siéntase libre, no creo que sea el único que se encuentre con este problema. – Femaref

14

Una mejor manera es utilizar un dispositivo de resolución del cliente. configuración de asignación está destinada a ser estática, por lo resolutores personalizados están destinados a proporcionar mapas para un solo miembro:

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

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

Luego, su resolución se convierte en:

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

configuración necesita para ejecutar una vez, por lo que la API de configuración proporciona ganchos en la API de ejecución (tipo de convertidores, resolutores de valor etc.)

+1

Conocía el ValueResolver, pero pensé que eran inútiles porque me faltaba la configuración de ConstructServicesUsing. ¡Buena esa! – Kugel

Cuestiones relacionadas