gpt4 book ai didi

c# - 重构两种方法以使用接口(interface)和/或泛型

转载 作者:行者123 更新时间:2023-11-30 22:05:08 29 4
gpt4 key购买 nike

我有一个程序可以为多种类型的类传递一些查询条件,EF 使用该程序从数据库中查询回数据。正在查询的每种类型都有一个标准类,但这些方法之间存在很多重复和相似之处,我希望重构它们,但没有成功。

这些是示例(简化的)服务方法:

private static IQueryable<Class1> FilterClass1ResultsOnId(Class1QueryCriteria queryCriteria, IQueryable<Class1> queryResults)
{
if (!string.IsNullOrEmpty(queryCriteria.Id))
{
queryResults = from view in queryResults where view.Id==queryCriteria.Id select view;
}
return queryResults;
}


private static IQueryable<Class2> FilterClass2ResultsOnId(Class2QueryCriteria queryCriteria, IQueryable<Class2> queryResults)
{
if (!string.IsNullOrEmpty(queryCriteria.Id))
{
queryResults = from view in queryResults where view.Id == queryCriteria.Id select view;
}
return queryResults;
}

...这样称呼...

queryResults = FilterClass1ResultsOnId(queryCriteria, queryResults);

服务有一系列这样的“FilterClassXonSOMECRITERIA”方法来缩小最终返回的 IQueryable 的范围。这些服务方法有很多,除了输入参数的类型和输出的类型外,它们本质上是相同的。

我最初尝试重构方法以接受 queryResults 参数,该参数是一个接口(interface)而不是具体类 - 一个只有 Id 属性的简单接口(interface) - 并且然后让 Class1Class2 实现该接口(interface)。但是如果我只想使用一种方法,我也需要使这些方法的返回类型不具体。这就是我卡住的地方。

我一直在四处寻找,看到了covariancecontravariance 的信息,但我似乎无法定义使用这些接口(interface)和泛型类型的方法/接口(interface)没有得到“无法解析符号 T”或“参数类型 XXX 不可分配给参数类型 YYY”。

在这一点上,我想与那些更熟悉这个问题的人进行理智检查:我正在尝试做的事情是否可行?我可以使用只接受由接口(interface)指定的参数的方法,并从该方法返回一个也只由接口(interface)指定的对象吗?

编辑:条件类非常简单,实际上是 EF 模型中定义的复杂类型。但这里有一个简化的例子:

public class Class1QueryCriteria
{
public string Id;
public string Name;
}

public class Class2QueryCriteria
{
public string Id;
public string Category;
}

最佳答案

您可以手动构建过滤器表达式:

private static Expression<Func<T, bool>> WhereById<T>(string id)
{
var pExpr = Expression.Parameter(typeof(T));
var idExpr = Expression.Property(pExpr, "Id");
var eqExpr = Expression.Equal(idExpr, Expression.Constant(id));
return Expression.Lambda<Func<T, bool>>(eqExpr, pExpr);
}

private static IQueryable<T> FilterById<T>(string id, IQueryable<T> source)
{
if (!string.IsNullOrEmpty(queryCriteria.Id))
{
var whereExpr = WhereById<T>(string id);
return source.Where(whereExpr);
}
return queryResults;
}

private static IQueryable<Class1> FilterClass1ResultsOnId(Class1QueryCriteria queryCriteria, IQueryable<Class1> queryResults)
{
return FilterById(queryCriteria.Id, queryResults);
}

如果您使用字符串 Id 属性创建基类型,则可以避免单独重载的需要。

或者,您可以使条件类通用并直接包含查询表达式,例如

public class QueryCriteria<T>
{
public Expression<Func<T, bool>> FilterExpression { get; set; }
}

然后你可以这样写:

public static IQueryable<T> FilterResults<T>(QueryCriteria<T> criteria, IQueryable<T> source)
{
return criteria.FilterExpression == null ? source : source.Where(criteria.FilterExpression);
}

关于c# - 重构两种方法以使用接口(interface)和/或泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24572483/

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