gpt4 book ai didi

c# - 协助重构 LINQ 方法

转载 作者:太空狗 更新时间:2023-10-29 23:53:43 24 4
gpt4 key购买 nike

我需要一些帮助,我有一个方法在我的类中重复了 6 次,每个方法中唯一改变的是 LINQ 属性(在示例“名字”中,但我还有一个用于姓氏、公司名称、用户 ID、状态)。我需要一些帮助来重构它,以便我可以只使用一种方法并将属性设置为动态的或传入的。

private static IQueryable<MyModel> FilterFirstName(IQueryable<MyModel> query, string searchText, string searchFilter)
{
switch (searchFilter.ToLower())
{
case "contains":
query = query.Where(x => x.FirstName.ToLower().Contains(searchText.ToLower()));
break;
case "does not contain":
query = query.Where(x => !x.FirstName.ToLower().Contains(searchText.ToLower()));
break;
case "starts with":
query = query.Where(x => x.FirstName.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase));
break;
case "ends with":
query = query.Where(x => x.FirstName.EndsWith(searchText, StringComparison.InvariantCultureIgnoreCase));
break;
case "equals":
query = query.Where(x => x.FirstName.Equals(searchText, StringComparison.InvariantCultureIgnoreCase));
break;
}

return query;
}

最佳答案

您可以使用 Compose 方法将一个表达式与另一个表达式组合起来:

public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");

var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);

return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}

它使用以下方法将一个表达式的所有实例替换为另一个表达式:

public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}

现在你可以写:

private static IQueryable<MyModel> FilterFirstName(
IQueryable<MyModel> query,
Expression<Func<MyModel, string>> selector,
string searchText,
string searchFilter)
{
switch (searchFilter.ToLower())
{
case "contains":
query = query.Where(selector.Compose(
text => text.ToLower().Contains(searchText.ToLower())));
break;
case "does not contain":
query = query.Where(selector.Compose(
text => !text.ToLower().Contains(searchText.ToLower())));
break;
case "starts with":
query = query.Where(selector.Compose(
text => text.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase)));
break;
case "ends with":
query = query.Where(selector.Compose(
text => text.EndsWith(searchText, StringComparison.InvariantCultureIgnoreCase)));
break;
case "equals":
query = query.Where(selector.Compose(
text => text.Equals(searchText, StringComparison.InvariantCultureIgnoreCase)));
break;
}

return query;
}

附带说明一下,您确实应该使用enum 来表示searchFilter 的不同类型的过滤器,而不是字符串。这将使调用者更容易,因为他们不需要在没有任何好方法知道确切选项是什么或提供的选项是否有效的情况下键入确切的字符串。

关于c# - 协助重构 LINQ 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28441983/

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