2014-10-14 7 views
12

Ho un database multilingue, che restituisce valori basati su una chiave e un enum Language. Quando converto un oggetto DB in un modello, voglio che il modello contenga il valore tradotto in base alla chiave e alla lingua corrente.passaggio di valori a un convertitore di tipo AutoMapper da esterno

La chiave proviene dall'oggetto DB, ma come posso passare la lingua corrente alla funzione Mapper.Map()?

Attualmente, sto utilizzando un attributo [ThreadStatic] per impostare la cultura prima di chiamare Mapper.Map<> e per recuperarla nello TypeConverter.

public enum Language 
{ 
    English, French, Italian, Maltese 
} 

public class MultilingualValue<T> 
{ 
    public Dictionary<Language, T> Value { get; set; } 
    public MultilingualValue() 
    { 
     this.Value = new Dictionary<Language, T>(); 
    } 
} 

public class PersonData 
{ 
    public string FirstName { get; set; } 
    public MultilingualValue<string> City { get; set; } 
} 

public void MapPerson() 
{ 
    PersonData personData = new PersonData(); 
    personData.FirstName = "John"; 
    personData.City = new MultilingualValue<string>(); 
    personData.City.Value[ Language.English] = "The Zurrieq"; 
    personData.City.Value[Language.French] = "Le Zurrieque"; 

    MultilingualValueData.CurrentLanguage = Language.English; 

    var personModel = Mapper.Map<PersonData, PersonModel>(personData); 
} 

public class MultilingualValueToBasicDataTypeConverter<T> : ITypeConverter<MultilingualValue<T>, T> 
{ 
    public T Convert(ResolutionContext context) 
    { 
     var currentLanguage = MultilingualValueData.CurrentLanguage; //THIS IS THE [ThreadStatic] VARIABLE 
     if (currentLanguage == null) throw new InvalidOperationException("Please make sure to fill in CurrentLanguage"); 

     MultilingualValue<T> sourceMultilingualValue = (MultilingualValue <T>)context.SourceValue; 

     T destinationValue = default(T); 
     if (sourceMultilingualValue != null) 
     { 
      destinationValue = sourceMultilingualValue.Value[currentLanguage.Value]; 
     } 

     return destinationValue; 
    } 
}   

public static class MultilingualValueData 
{ 
    [ThreadStatic] 
    public static Language? CurrentLanguage; 
} 

Ho omesso le configurazioni perché penso che non siano necessarie per questo esempio. Se ne hai bisogno, li posterò anch'io.

Mentre funziona, trovo questa soluzione abbastanza brutta. C'è un modo per passare i dati attraverso lo ResolutionContext?

risposta

16

Utilizzare solo il sovraccarico Map che accetta uno Action<IMappingOperationOptions>. È possibile aggiungere elementi di configurazione alla proprietà Items che vengono poi passati al vostro ITypeConverter

public class CustomConverter : ITypeConverter<string, string> 
{ 
    public string Convert(ResolutionContext context) 
    { 
     return "translated in " + context.Options.Items["language"]; 
    } 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     AutoMapper.Mapper.CreateMap<string, string>().ConvertUsing<CustomConverter>(); 
     var result = AutoMapper.Mapper.Map<string, string>("value" , opt => opt.Items["language"] = "english"); 
     Console.Write(result); // prints "translated in english" 
     Console.ReadLine(); 
    } 
} 
+0

perfetto, proprio quello che volevo! :) –

+0

Sono costretto a utilizzare una versione precedente di AutoMapper che non supporta opt.Items. C'è un'alternativa? –

+0

Come si possono aggiungere 2 elementi al dizionario 'Items'? –

Problemi correlati