2015-03-04 11 views
6

Mam następujących klas domeny i Dto klasy:Korzystanie AutoMapper mapować ciąg do wyliczenia

public class Profile 
{ 
    public string Name { get; set; } 
    public string SchoolGrade { get; set; } 
} 

public class ProfileDTO 
{ 
    public string Name { get; set; } 
    public SchoolGradeDTO SchoolGrade { get; set; } 
} 

public enum SchoolGradeDTO 
{ 
    [Display(Name = "Level One"] 
    LevelOne, 
    [Display(Name = "Level Two"] 
    LevelTwo, 
} 

użyłem następujące metody:

Mapper.CreateMap<Profile, ProfileDTO>() 
     .ForMember(d => d.SchoolGrade , op => op.MapFrom(o => o.SchoolGrade)) 

Następnie pojawia się następujący błąd:

Requested value 'Level Two' was not found.

Jak poprawnie odwzorować?

+0

Jaki jest powód, dla którego podajesz wartość atrybutu wyświetlanego dla wyliczenia? To znaczy. dlaczego używasz "Poziom 2" zamiast "LevelTwo". Wykonanie tego sprawia, że ​​zadanie to jest nieco trudniejsze (wymagać będzie refleksji w celu rozwiązania). – Umair

+0

Użycie 'LevelTwo' pozwoli automatowi mapować bezpośrednio (nie ma potrzeby stosowania bitu' ForMember') – Umair

+0

Jakie jest pytanie? –

Odpowiedz

11

nie Skoro mapowania z nazwą wyświetlacza a enum nazwa musisz buid niestandardową funkcję mapowania skanowania atrybuty znaleźć wyliczenia o tej nazwie wyświetlacza. Można użyć ResolveUsing zamiast MapFrom użyć funkcji mapowania niestandardowe:

Mapper.CreateMap<Profile, ProfileDTO>() 
     .ForMember(d => d.SchoolGrade, 
       op => op.ResolveUsing(o=> MapGrade(o.SchoolGrade))); 

public static SchoolGradeDTO MapGrade(string grade) 
{ 
    //TODO: function to map a string to a SchoolGradeDTO 
} 

Można buforować nazwiska w statycznym słowniku więc nie wykorzystać odbicie każdym razem.

kilka metod prowadzenia, które można znaleźć here.

6

Rozszerzając odpowiedź D Stanley jest z góry w nieco bardziej szczegółowo i zmodyfikował EnumHelper class from this other discussion skupić się na konkretnej sytuacji, jak ta kwestia naprawdę obejmuje dwa obszary, AutoMapper i prawidłowo uzyskania wartość enum jest z ciągiem.

Zwiększanie oryginalną odpowiedź D Stanley „s

public static class QuestionAutoMapperConfig 
{ 
    public static void ConfigureAutoMapper() 
    { 
     Mapper.CreateMap<Profile, ProfileDTO>() 
      .ForMember(d => d.SchoolGrade, 
       op => op.ResolveUsing(o => MapGrade(o.SchoolGrade))); 
    } 

    public static SchoolGradeDTO MapGrade(string grade) 
    { 
     //TODO: function to map a string to a SchoolGradeDTO 
     return EnumHelper<SchoolGradeDTO>.Parse(grade); 
    } 
} 

Mam poprawił EnumHelper ze wspomnianego przykładu, aby szybko wyświetlić opcję gdzie przez można zmodyfikować metody Parse aby najpierw spróbować standardowego Enum. Parse() i nieudane, aby spróbować wykonać bardziej szczegółowe porównanie typu Enum, tworząc słownik wartości oparty na nazwie wartości wyliczeniowej lub jego atrybucie wyświetlania (jeśli jest używany).

public static class EnumHelper<T> 
{ 
    public static IDictionary<string, T> GetValues(bool ignoreCase) 
    { 
     var enumValues = new Dictionary<string, T>(); 

     foreach (FieldInfo fi in typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public)) 
     { 
      string key = fi.Name; 

      var display = fi.GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[]; 
      if (display != null) 
       key = (display.Length > 0) ? display[0].Name : fi.Name; 

      if (ignoreCase) 
       key = key.ToLower(); 

      if (!enumValues.ContainsKey(key)) 
       enumValues[key] = (T)fi.GetRawConstantValue(); 
     } 

     return enumValues; 
    } 

    public static T Parse(string value) 
    { 
     T result; 

     try 
     { 
      result = (T)Enum.Parse(typeof(T), value, true); 
     } 
     catch (Exception) 
     { 
      result = ParseDisplayValues(value, true); 
     } 


     return result; 
    } 

    private static T ParseDisplayValues(string value, bool ignoreCase) 
    { 
     IDictionary<string, T> values = GetValues(ignoreCase); 

     string key = null; 
     if (ignoreCase) 
      key = value.ToLower(); 
     else 
      key = value; 

     if (values.ContainsKey(key)) 
      return values[key]; 

     throw new ArgumentException(value); 
    } 
} 
Powiązane problemy