2014-10-14 7 views
12

Ich habe eine mehrsprachige Datenbank, die Werte basierend auf einem Schlüssel und einem Enum Language zurückgibt. Wenn ich ein DB-Objekt in ein Modell umwandle, möchte ich, dass das Modell den übersetzten Wert basierend auf dem Schlüssel und der aktuellen Sprache enthält.Weitergabe von Werten an einen AutoMapper Type Converter von außerhalb

Der Schlüssel kommt vom DB-Objekt, aber wie kann ich die aktuelle Sprache an die Mapper.Map()-Funktion übergeben?

Derzeit verwende ich ein [ThreadStatic] Attribut, um die Kultur vor dem Aufruf Mapper.Map<> einzustellen, und in der TypeConverter abrufen.

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

Ich habe die Konfigurationen weggelassen, da ich denke, dass sie für dieses Beispiel nicht notwendig sind. Wenn Sie sie brauchen, werde ich sie auch veröffentlichen.

Während dies funktioniert, finde ich diese Umgehungslösung ziemlich hässlich. Gibt es eine Möglichkeit, Daten über die ResolutionContext zu übergeben?

Antwort

16

Verwenden Sie einfach die Map Überladung, die eine Action<IMappingOperationOptions> dauert. Sie können Konfigurationselemente an die Items Eigenschaft hinzufügen, die dann auf Ihre ITypeConverter geben werden

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

perfekt, was nur ich wollte! :) –

+0

Ich bin gezwungen, eine ältere Version von AutoMapper zu verwenden, die opt.Items nicht unterstützt. Gibt es eine Alternative? –

+0

Wie können Sie dem 'Items' Wörterbuch 2 Elemente hinzufügen? –

Verwandte Themen