WebAPI-基于实体修饰属性的通用搜索服务

hsnslh

我想创建一个通用服务,该服务仅通过其修饰的属性(通过自定义属性)在特定实体中进行搜索,而我尝试使用表达式来执行此操作,但我想我缺少了一些东西。这里是一个示例代码:

服务

public class MyService<TEntity>
    where TEntity: class
{
    private readonly MyContext context;

    public MyService()
    {
        this.context = new MyContext();
    }

    private Func<TEntity, string, bool> searchFunc = (e, search) =>
    {
        var type = typeof(TEntity);
        var props = type.GetProperties().Where(p => p.GetCustomAttributes(typeof(SearchPropertyAttribute), true).Any());

        Expression expression = Expression.Constant(false);
        foreach (var prop in props)
        {
            expression = Expression.MakeBinary(ExpressionType.Or,
                                                expression,
                                                Expression.MakeBinary(ExpressionType.Equal,
                                                                        Expression.Property(Expression.Constant(e), prop.Name),
                                                                        Expression.Constant(search)));
        }

        var delegateFunc = Expression.Lambda<Func<TEntity, string, bool>>(expression).Compile();
        return delegateFunc(e, search);
    };

    /// <summary>
    /// searches in specified entity set the given string using only decorated properties.
    /// </summary>
    public List<TEntity> Find(string search)
    {
        var list = this.context.Set<TEntity>().Where(e => searchFunc(e as TEntity, search));
        return list.ToList() as List<TEntity>;
    }
}

实体

public class MyEntity
{
    [SearchProperty]
    public string FirstName { get; set; }

    [SearchProperty]
    public string LastName { get; set; }

    public string Description { get; set; }
}

我只想限制由SearchProperty属性装饰的属性的搜索谢谢

吉列尔莫·贝隆(Guillermo Veron)

我已经在最近的项目中实现了该功能,并为此在基本控制器中创建了以下方法:

获取实体的可过滤道具:

private List<PropertyInfo> GetFilterProps()
{
    var t = typeof(TEntity);
    var props = t.GetProperties();
    var filterProps = new List<PropertyInfo>();

    foreach (var prop in props)
    {
        var attr = (SearchProperty[])prop.GetCustomAttributes(typeof(SearchProperty), false);
        if (attr.Length > 0)
        {
            filterProps.Add(prop);
        }
     }

     return filterProps;
}

使用表达式树生成动态查询:

private IQueryable<TEntity> Filter(IQueryable<TEntity> query, string value)
{
    if (string.IsNullOrEmpty(value) || this.filterProps.Count == 0) return query;

    ConstantExpression constant = Expression.Constant(value.ToLower());
    ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "e");
    MemberExpression[] members = new MemberExpression[filterProps.Count()];
    MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
    MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", System.Type.EmptyTypes);

    for (int i = 0; i < filterProps.Count(); i++)
    {
        members[i] = Expression.Property(parameter, filterProps[i]);
    }

    Expression predicate = null;
    foreach (var member in members)
    {
        //e => e.Member != null
        BinaryExpression notNullExp = Expression.NotEqual(member, Expression.Constant(null));
        //e => e.Member.ToLower() 
        MethodCallExpression toLowerExp = Expression.Call(member, toLowerMethod);
        //e => e.Member.Contains(value)
        MethodCallExpression containsExp = Expression.Call(toLowerExp, containsMethod, constant);
        //e => e.Member != null && e.Member.Contains(value)
        BinaryExpression filterExpression = Expression.AndAlso(notNullExp, containsExp);

        predicate = predicate == null ? (Expression)filterExpression : Expression.OrElse(predicate, filterExpression);
    }

    var lambda = Expression.Lambda<Func<TEntity, bool>>(predicate, parameter);

    return query.Where(lambda);
}

在您的Get方法中,您将获得类似以下内容的信息:

[HttpGet]
public virtual async Task<IActionResult> List([FromQuery] string filter)
{
    var query = _context.Set<TEntity>();

    query = Filter(query, filter);

    var result = await query.ToListAsync();

    return Ok(result);
}    

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章