如何在可查询投影期间使用 AutoMapper 将 int 映射到其枚举描述?

2023-12-01

这是获取其描述属性的枚举扩展方法。

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

这是源对象:

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

这是枚举:

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

这是目标对象:

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

这是我尝试映射(使用最新的非静态自动映射器版本)。请记住,这是在 EF 可查询投影期间。

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

这是投影,其中查询是IQueryable<Account>:

query.ProjectToList<GetAccountResponse>(_config);

这是我得到的异常:

无法将此解析为可查询表达式


如果您检查 MapFrom 方法的签名,您会注意到其中一个重载采用以下类型的参数Expression<Func<TSource, TMember>>.

这表明您可以编写一个从三元表达式构建表达式树的方法,该方法可以将枚举的任何可能值转换为其适当的字符串。然后,AutoMapper 会通过 LINQ 将其转换为适当的 SQL 表达式。

这是一个仅使用枚举名称本身的示例:您应该能够直接调整它以使用您的描述:

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

您可以按如下方式使用它:

CreateMap<Entry, EntryListItem>()
            .ForMember(e => e.ReviewStatus,
                c => c.MapFrom(EnumerableExpressionHelper.CreateEnumToStringExpression((Entry e) => e.ReviewStatus)))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在可查询投影期间使用 AutoMapper 将 int 映射到其枚举描述? 的相关文章

随机推荐