为自定义LINQ提供程序实现Select



我很理解实现Linq的方法,但我在这里遇到的一个小问题是,我正在实现一个Linq到树的对象,树本身就是一个简单的树实现,所以我从创建可查询对象开始

public class TreeContext<T> : IOrderedQueryable where T :IComparable<T>
{
private Tree<T> _root;
private Expression _expression;
private IQueryProvider _provider;
public TreeContext(Tree<T> root)
{
_root = root;
Provider = new TreeProvider<T>(_root);
}
public TreeContext(IQueryProvider provider, Expression expression)
{
Provider = provider;
Expression = expression;
}
#region Model 
public IEnumerable<TResult> Select<TResult>(Func<T,TResult> predicate)
{
var param = predicate.Method.GetParameters()[0];


return null;
}

public IEnumerable<T> Where(Func<T, bool> predicate)
{


Provider.Execute<IEnumerable>(Expression);
return null;
}
#endregion

public Expression Expression 
{ 
private set { _expression = value; } 
get { return _expression; } 
}
public Type ElementType => typeof(T);
public IQueryProvider Provider
{
private set { _provider = value; }
get { return _provider; }
}

public IEnumerator<T> GetEnumerator()
=> GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=>Provider.Execute<IEnumerable>(Expression).GetEnumerator();

}

然后我实现了QueryProvider,这里存在的问题,正是在选择方法实现上

public class TreeProvider<T> : IQueryProvider where T:IComparable<T>
{
private Tree<T> _root;
public TreeProvider(Tree<T> root)
=> _root = root;

public IQueryable CreateQuery(Expression expression)
=> new TreeContext<T>(this, expression);
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
=>throw new NotImplementedException();

public object Execute(Expression expression)
=> new TreeQueryContext<T>(_root).Execute(expression);

public TResult Execute<TResult>(Expression expression)
{
throw  new NotImplementedException();
}
}

没有为此自定义提供程序提供select实现,因此我可以编写如下请求从上下文中的el选择el

我添加了一个方法选择

IEnumerable Select<T、 TResult>(函数<T,TResult>选择器(

问题是,我没有找到一种方法将这个选择器转换为表达式,以便将其传递给QueryProvider的执行方法

也许我不太了解如何开发一个自定义LINQ到自定义提供商,我在C#中也没有找到任何关于这方面的好的完整教程

如果您想创建LINQ Provider,您必须始终使用表达式树来创建和解析查询。

TreeContext中的SelectWhere根本不需要。标准LINQ扩展具有这些方法,并将自动为您准备表达式树。重点关注TreeProvider的实施。

由于您是该领域的新手,我建议您将LINQ提供程序建立在Relink上。它将从一开始就简化你的生活,并展示可能的实施方式。它有用于Provider和Query实现的基类,但不需要从它们派生。

试试

var queryParser = new QueryParser(new ExpressionTreeParser(
ExpressionTreeParser.CreateDefaultNodeTypeProvider(),
ExpressionTreeParser.CreateDefaultProcessor(
ExpressionTransformerRegistry.CreateDefault(),
null)));
var queryModel = parser.GetParsedQuery(expression);

Relink将为您提供QueryModel,它更容易解析。

最新更新