【发布时间】:2018-03-05 13:31:04
【问题描述】:
我正在编写自定义 IQueryable,以使用 Web 服务。 Web 服务的查询功能有限。 所以我想要的是,在我的 IQueryable 中查询 Web 服务,然后对来自 Web 服务的数据执行给定的表达式。
我的 IQueryable 实现如下所示:
public class CloudInfoQuery : IQueryable<CloudContentModel>
{
private string _accessToken;
public Type ElementType => typeof(CloudContentModel);
public Expression Expression
{
get;
private set;
}
public IQueryProvider Provider
{
get;
private set;
}
internal CloudInfoQuery(string accessToken)
{
_accessToken = accessToken;
Provider = new CloudInfoProvider(accessToken);
Expression = Expression.Constant(this);
}
internal CloudInfoQuery(string accessToken, IQueryProvider provider, Expression expression) : this(accessToken)
{
Provider = provider;
Expression = expression;
}
public IEnumerator<CloudContentModel> GetEnumerator()
{
return Provider.Execute<IEnumerable<CloudContentModel>>(Expression).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
我在IQueryProvider 中的Execute 看起来像这样:
public object Execute(Expression expression)
{
List<CloudContentModel> cloudContent = GetContentFromWebService(expression);
return cloudContents.AsQueryable().Provider.Execute(mExpression):
}
我正在分析查询中可能的过滤器,并将它们用于 Web 服务调用。 之后,我想对结果执行表达式,以便应用所有过滤器,这些过滤器不受 web 服务支持。
但是当我这样做时,会出现无限循环,因为我的CloudInfoQuery 中有Expression = Expression.Constant(this);。
我试图删除表达式,这会导致表达式树出现无限循环,或者通过更新 MethodCallExpression 来更改它。
但随后我将面对System.ArgumentException: Static method requires null instance, non-static method requires non-null instance。
接下来,我尝试过并导致上述异常:
从树中删除表达式
MethodCallExpression mExpression = expression as MethodCallExpression;
mExpression = mExpression.Update(expression, mExpression.Arguments.Skip(1));
使用新的表达式更新到
MethodCallExpression mExpression = expression as MethodCallExpression;
mExpression = mExpression.Update(Expression.Constant(cloudContents), mExpression.Arguments.Skip(1));
在表达式树的顶部设置一个新的表达式
MethodCallExpression mExpression = expression as MethodCallExpression;
List<Expression> exs = new List<Expression>();
exs.Add(Expression.Constant(cloudContents));
exs.AddRange(mExpression.Arguments.Skip(1));
mExpression = mExpression.Update(expression, exs);
我也试图阻止这样的无限循环:
private IEnumerabe<CloudContentModel> _cloudContents;
public object Execute(Expression expression)
{
if(_cloudContents != null)
{
return _cloudContents;
}
List<CloudContentModel> cloudContent = GetContentFromWebService(expression);
_cloudContents = cloudContents.AsQueryable().Provider.Execute(mExpression);
return _cloudContents:
}
但是额外的过滤器将不起作用。 那么如何将表达式传递给另一个 List 呢?
【问题讨论】: