您的位置:知识库 »

打造自己的LINQ Provider(中):IQueryable和IQueryProvider

作者: TerryLee  来源: 博客园  发布时间: 2008-09-19 23:25  阅读: 14967 次  推荐: 2   原文链接   [收藏]  
摘要:本文为打造自己的LINQ Provider系列文章第二篇,主要详细介绍自定义LINQ Provider中两个最重要的接口IQueryable和IQueryProvider。
[1] IEnumerable接口1
[2] IEnumerable接口2
[3] IQueryable接口
[4] IQueryProvider接口
[5] 扩展LINQ的两种方式
[6] 总结

扩展LINQ的两种方式

通过前面的讲解,我们可以想到,对于LINQ的扩展有两种方式,一是借助于LINQ to Objects,如果我们所做的查询直接在.NET代码中执行,就可以实现IEnumerable<T>接口,而无须再去实现IQueryable并编写自定义的LINQ Provider,如.NET中内置的List<T>等。如我们可以编写一段简单自定义代码:

public class MyData<T> : IEnumerable<T>
                where T : class
{
    public IEnumerator<T> GetEnumerator()
    {
        return null;
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return null;
    }
 
    // 其它成员
}

第二种扩展LINQ的方式当然就是自定义LINQ Provider了,我们需要实现IQueryable<T>和IQueryProvider两个接口,下面先给出一段简单的示意代码,在下一篇中我们将完整的来实现一个LINQ Provider。如下代码所示:

public class QueryableData<TData> : IQueryable<TData>
{
    public QueryableData()
    {
        Provider = new TerryQueryProvider();
        Expression = Expression.Constant(this);
    }
 
    public QueryableData(TerryQueryProvider provider, 
        Expression expression)
    {
        if (provider == null)
        {
            throw new ArgumentNullException("provider");
        }
 
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }
 
        if (!typeof(IQueryable<TData>).IsAssignableFrom(expression.Type))
        {
            throw new ArgumentOutOfRangeException("expression");
        }
 
        Provider = provider;
        Expression = expression;
    }
 
    public IQueryProvider Provider { get; private set; }
    public Expression Expression { get; private set; }
 
    public Type ElementType
    {
        get { return typeof(TData); }
    }
 
    public IEnumerator<TData> GetEnumerator()
    {
        return (Provider.Execute<IEnumerable<TData>>(Expression)).GetEnumerator();
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return (Provider.Execute<IEnumerable>(Expression)).GetEnumerator();
    }
}
 
public class TerryQueryProvider : IQueryProvider
{
    public IQueryable CreateQuery(Expression expression)
    {
        Type elementType = TypeSystem.GetElementType(expression.Type);
        try
        {
            return (IQueryable)Activator.CreateInstance(
                typeof(QueryableData<>).MakeGenericType(elementType),
                new object[] { this, expression });
        }
        catch
        {
            throw new Exception();
        }
    }
 
    public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
    {
        return new QueryableData<TResult>(this, expression);
    }
 
    public object Execute(Expression expression)
    {
        // ......
    }
 
    public TResult Execute<TResult>(Expression expression)
    {
        // ......
    }
}
2
0

热门文章

    最新文章

      最新新闻

        热门新闻