【问题标题】:Implement the Select for a custom LINQ provider为自定义 LINQ 提供程序实现 Select
【发布时间】:2020-10-21 02:35:39
【问题描述】:

我非常了解实现 Linq 的方式,但是我在这里遇到的一个小问题是这种情况,我正在实现一个 Linq to Tree 对象,它本身就是简单的 Tree 实现,所以我从创建 Queryable 开始对象

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,问题就出在这里,就在 select 方法实现

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

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

我添加了一个方法选择

IEnumerable Select(Func 选择器)

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

也许我不太了解如何开发自定义 LINQ 到自定义提供程序,并且我没有在 C# 中找到任何好的和完整的教程

【问题讨论】:

    标签: linq provider


    【解决方案1】:

    如果您想创建 LINQ 提供程序 - 您必须始终处理表达式树来创建和解析查询。

    您的TreeContext 中的SelectWhere 根本不需要。标准 LINQ 扩展具有这些方法,并会自动为您准备表达式树。专注于TreeProvider 的实现。

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

    试试吧

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

    Relinq 会给你QueryModel,这更容易解析。

    【讨论】:

    • 谢谢你 Svyatoslav Danyliv 我需要试一试,你说 Select 和 Where in your TreeContext 根本不需要我知道它们是由 IQueryable 接口作为扩展方法提供的,但是当我尝试这个时var query = from el in treecontext select el 它回应我没有对应的选择实现树上下文我不明白这一点
    • 您必须在 .cs 文件的顶部添加 using System.Linq;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    相关资源
    最近更新 更多