gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 11:57:29 25 4
gpt4 key购买 nike

我想创建一个通用服务,该服务仅通过其装饰属性(通过自定义属性)在特定实体中进行搜索我尝试使用表达式来做到这一点,但我想我遗漏了一些东西。这里有一个示例代码:

服务

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 属性修饰的属性上谢谢

最佳答案

我在最近的项目中实现了该功能,为此我在我的基本 Controller 中创建了以下方法:

获取实体的可过滤属性:

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

关于c# - WebAPI - 基于实体修饰属性的通用搜索服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58939102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com