2

Hier ist die Enum-Extension-Methode, um seine Beschreibung Attribut zu erhalten.Wie wird ein Int mit einer AutoMapper während einer abfragbaren Projektion seiner Enum-Beschreibung zugeordnet?

public static string GetDescription(this Enum enumeration) 
{ 
    if (enumeration == null) 
     throw new ArgumentNullException(); 

    var value = enumeration.ToString(); 
    var type = enumeration.GetType(); 
    var descriptionAttribute = 
     (DescriptionAttribute[]) type.GetField(value).GetCustomAttributes(typeof (DescriptionAttribute), false); 

    return descriptionAttribute.Length > 0 ? descriptionAttribute[0].Description : value; 
} 

ist hier das Quellobjekt:

public class Account { 
    public int AccountId {get;set;} 
    public int AccountStatusId {get;set;} 
} 

Hier ist die Enum ist:

public enum AccountStatus { 
    [Description("N/A")] 
    None, 
    [Description("OPEN")] 
    Open, 
    [Description("CLOSED")] 
    Closed, 
    [Description("BAD CREDIT") 
    Problem 
} 

Hier ist das Zielobjekt:

public class GetAccountResponse { 
    public int AccountId {get;set;} 
    public string Status {get;set;} 
} 

Hier ist mein Versuch, Karte (mit dem neusten nicht-statischen Automapp r Version). Denken Sie daran, dass dies während einer EF-abfragbaren Projektion geschieht.

_config = new MapperConfiguration(cfg => cfg.CreateMap<Account, GetAccountsResponse>() 
    .ForMember(dest => dest.Status, 
     opts => opts.MapFrom(src => ((AccountStatus) src.AccountStatusId).GetDescription()))); 

ist die Projektion, wo Abfrage eine ist IQueryable<Account>:

query.ProjectToList<GetAccountResponse>(_config); 

Das ist die Ausnahme, die ich erhalten:

Kann diese Expression abfragbaren nicht lösen

Antwort

1

Wenn Sie die Signatur der MapFrom-Methode auschecken, werden Sie Beachten Sie, dass eine der Überladungen einen Parameter vom Typ Expression<Func<TSource, TMember>> annimmt.

Dies deutet darauf hin, dass Sie eine Methode schreiben könnten, die einen Ausdrucksbaum aus ternären Ausdrücken erstellt, die jeden möglichen Wert Ihrer Enumeration in die entsprechende Zeichenfolge konvertieren können. AutoMapper würde dies dann über LINQ in den entsprechenden SQL-Ausdruck konvertieren.

Hier ist ein Beispiel, das die Enum-Namen selbst nur verwendet: Sie sollten in der Lage sein, ohne weiteres anpassen Ihre Beschreibungen verwenden:

public static class EnumerableExpressionHelper 
{ 
    public static Expression<Func<TSource, String>> CreateEnumToStringExpression<TSource, TMember>(
     Expression<Func<TSource, TMember>> memberAccess, string defaultValue = "") 
    { 
     var type = typeof(TMember); 
     if (!type.IsEnum) 
     { 
      throw new InvalidOperationException("TMember must be an Enum type"); 
     } 

     var enumNames = Enum.GetNames(type); 
     var enumValues = (TMember[])Enum.GetValues(type); 

     var inner = (Expression)Expression.Constant(defaultValue); 

     var parameter = memberAccess.Parameters[0]; 

     for (int i = 0; i < enumValues.Length; i++) 
     { 
      inner = Expression.Condition(
      Expression.Equal(memberAccess.Body, Expression.Constant(enumValues[i])), 
      Expression.Constant(enumNames[i]), 
      inner); 
     } 

     var expression = Expression.Lambda<Func<TSource,String>>(inner, parameter); 

     return expression; 
    } 
} 

Sie würden es wie folgt verwenden:

CreateMap<Entry, EntryListItem>() 
      .ForMember(e => e.ReviewStatus, 
       c => c.MapFrom(EnumerableExpressionHelper.CreateEnumToStringExpression((Entry e) => e.ReviewStatus)))