gpt4 book ai didi

c# - 在 List 上执行表达式

转载 作者:太空宇宙 更新时间:2023-11-03 22:47:47 24 4
gpt4 key购买 nike

我正在编写自定义 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();
}
}

我的 ExecuteIQueryProvider看起来像这样:

public object Execute(Expression expression)
{
List<CloudContentModel> cloudContent = GetContentFromWebService(expression);
return cloudContents.AsQueryable().Provider.Execute(mExpression):
}

我正在分析查询中可能的过滤器并将它们用于网络服务调用。之后,我想对结果执行表达式,以便应用所有过滤器,而这些过滤器不受 web 服务支持。

但是当我这样做的时候,会出现死循环,因为Expression = Expression.Constant(this);在我的 CloudInfoQuery .

我试图从表达式树中删除导致无限循环的表达式,或者通过更新 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:
}

但是附加的过滤器将不起作用。那么如何将表达式传递给另一个列表呢?

最佳答案

好的,感谢相关部分,我找到了一个受此启发的解决方案:How do you transfer the execution of a Expression created by an IQueryable object to a IEnumerable?

public class CloudInfoQuery : IQueryable<CloudContentModel>
{
private string _accessToken;
private List<CloudContentModel> _cloudContents = new List<CloudContentModel>();

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, _cloudContents);
Expression = _cloudContents.AsQueryable().Expression;
}

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

public class CloudInfoProvider : IQueryProvider
{
private string _accessToken;
private List<CloudContentModel> _cloudContents = null;

public CloudInfoProvider(string accessToken, List<CloudContentModel> cloudContent)
{
_accessToken = accessToken;
_cloudContents = cloudContent;
}

public IQueryable CreateQuery(Expression expression)
{
return new CloudInfoQuery(_accessToken, this, expression);
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return (IQueryable<TElement>)new CloudInfoQuery(_accessToken, this, expression);
}

public object Execute(Expression expression)
{
_cloudContent.Clear();
_cloudContent.AddRange(GetContentFromWebService(expression));
return cloudContents.AsQueryable().Provider.CreateQuery(expression):
}

public TResult Execute<TResult>(Expression expression)
{
return (TResult)Execute(expression);

}
}

诀窍是,使用来自同一实例的表达式,稍后将包含要过滤的数据。

Expression = _cloudContents.AsQueryable().Expression;

关于c# - 在 List 上执行表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49111614/

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