Создание выражения Linq для преобразования int в имя enum в проекции AutoMapper - PullRequest
0 голосов
/ 16 мая 2019

Я бы хотел упростить отображение моего текущего представления модели. В настоящее время я использую Automapper ProjectTo для создания модели представления, а затем вызываю метод post mapping для заполнения свойства StatusDescription string из перечисления Status, значение которого находится в другом свойстве int в классе модели представления, StatusId.

Я нашел этот другой ответ , но я не могу заставить его работать, и мне трудно понять, что именно он делает из-за моего общего недостатка опыта в выражениях.

Для справки, вот метод выражения (заметьте, мне пришлось закомментировать параметр defaultValue, когда я получал ошибку An expression tree may not contain a call or invocation that uses optional arguments:

public static Expression<Func<TSource, String>> CreateEnumToStringExpression<TSource, TMember>(
    Expression<Func<TSource, TMember>> memberAccess)//,string defaultValue = ""
{
    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;
}

Я называю это так:

.ForMember(dest => dest.Status, option =>
    option.MapFrom(src =>
        EnumHelper.ExpressionHelper
        .CreateEnumToStringExpression((ShippingContainerHeader s) => s.StatusId)
    ))

Ошибка, которую я получаю при запуске: LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression..

A.) Думаю, я ошибаюсь, может быть? Разве я не должен использовать ссылку на src в вызове метода MapFrom, чтобы передать фактическое значение StatusId в метод выражения?

B.) Кажется, есть проблема с методом генерации выражений, так как он вызывает ошибку ToString(). В этом методе нет явного вызова .ToString(), но он должен как-то подразумеваться.

C.) Понимание кода: я могу следовать всему коду внутри метода CreateEnumToStringExpression, за исключением того, что является переменной parameter и последним оператором выражения переменной expression. Кроме того, универсальные типы, в которых я запутался ... есть много универсальных типов, и вызов метода из связанного примера не определяет явно ни один из них.

В Expression<Func<TSource, String>> Я уверен, что TSource - это вход, который является int. String - это вывод, который будет именем enum.

В CreateEnumToStringExpression<TSource, TMember> и Expression<Func<TSource, TMember>> memberAccess: TSource снова равно int, TMember является типом класса enum.

Но вам не нужно явно вызывать их при вызове метода? Что-то вроде: CreateEnumToStringExpression<int, StatusesEnum>(new Expression<Func<int, ShippingContainerHeader>> { s => s.StatusId })

...