2013-09-24 30 views
6

Tôi đã làm việc với API TFS cho VS2010 và phải truy vấn FieldCollection mà tôi thấy không được LINQ hỗ trợ nên tôi muốn tạo một lớp tùy chỉnh để làm cho Field và FieldCollection có thể truy vấn được bởi LINQ tôi tìm thấy một mẫu cơ bản và cố gắng thực hiện nóTạo một lớp tùy chỉnh IQueryable

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using Microsoft.TeamFoundation.WorkItemTracking.Client; 

public class WorkItemFieldCollection : IQueryable<Field>, IQueryProvider 
{ 
    private List<Field> _fieldList = new List<Field>(); 

    #region Constructors 

    /// <summary> 
    /// This constructor is called by the client to create the data source. 
    /// </summary> 
    public WorkItemFieldCollection(FieldCollection fieldCollection) 
    { 
     foreach (Field field in fieldCollection) 
     { 
      _fieldList.Add(field); 
     } 

    } 

    #endregion Constructors 

    #region IQueryable Members 

    Type IQueryable.ElementType 
    { 
     get { return typeof(Field); } 
    } 

    System.Linq.Expressions.Expression IQueryable.Expression 
    { 
     get { return Expression.Constant(this); } 
    } 

    IQueryProvider IQueryable.Provider 
    { 
     get { return this; } 
    } 

    #endregion IQueryable Members 

    #region IEnumerable<Field> Members 

    IEnumerator<Field> IEnumerable<Field>.GetEnumerator() 
    { 
     return (this as IQueryable).Provider.Execute<IEnumerator<Field>>(_expression); 
    } 

    private IList<Field> _field = new List<Field>(); 
    private Expression _expression = null; 

    #endregion IEnumerable<Field> Members 

    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return (IEnumerator<Field>)(this as IQueryable).GetEnumerator(); 
    } 

    private void ProcessExpression(Expression expression) 
    { 
     if (expression.NodeType == ExpressionType.Equal) 
     { 
      ProcessEqualResult((BinaryExpression)expression); 
     } 
     if (expression is UnaryExpression) 
     { 
      UnaryExpression uExp = expression as UnaryExpression; 
      ProcessExpression(uExp.Operand); 
     } 
     else if (expression is LambdaExpression) 
     { 
      ProcessExpression(((LambdaExpression)expression).Body); 
     } 
     else if (expression is ParameterExpression) 
     { 
      if (((ParameterExpression)expression).Type == typeof(Field)) 
      { 
       _field = GetFields(); 
      } 
     } 
    } 

    private void ProcessEqualResult(BinaryExpression expression) 
    { 
     if (expression.Right.NodeType == ExpressionType.Constant) 
     { 
      string name = (String)((ConstantExpression)expression.Right).Value; 
      ProceesItem(name); 
     } 
    } 

    private void ProceesItem(string name) 
    { 
     IList<Field> filtered = new List<Field>(); 

     foreach (Field field in GetFields()) 
     { 
      if (string.Compare(field.Name, name, true) == 0) 
      { 
       filtered.Add(field); 
      } 
     } 
     _field = filtered; 
    } 

    private object GetValue(BinaryExpression expression) 
    { 
     if (expression.Right.NodeType == ExpressionType.Constant) 
     { 
      return ((ConstantExpression)expression.Right).Value; 
     } 
     return null; 
    } 

    private IList<Field> GetFields() 
    { 
     return _fieldList; 
    } 

    #endregion IEnumerable Members 

    #region IQueryProvider Members 

    IQueryable<S> IQueryProvider.CreateQuery<S>(System.Linq.Expressions.Expression expression) 
    { 
     if (typeof(S) != typeof(Field)) 
      throw new Exception("Only " + typeof(Field).FullName + " objects are supported."); 

     this._expression = expression; 

     return (IQueryable<S>)this; 
    } 

    IQueryable IQueryProvider.CreateQuery(System.Linq.Expressions.Expression expression) 
    { 
     return (IQueryable<Field>)(this as IQueryProvider).CreateQuery<Field>(expression); 
    } 

    TResult IQueryProvider.Execute<TResult>(System.Linq.Expressions.Expression expression) 
    { 
     MethodCallExpression methodcall = _expression as MethodCallExpression; 

     foreach (var param in methodcall.Arguments) 
     { 
      ProcessExpression(param); 
     } 
     return (TResult)_field.GetEnumerator(); 
    } 

    object IQueryProvider.Execute(System.Linq.Expressions.Expression expression) 
    { 

     return (this as IQueryProvider).Execute<IEnumerator<Field>>(expression); 
    } 

    #endregion IQueryProvider Members 
} 

nó xuất hiện để biên dịch và được công nhận bởi LINQ nhưng tôi cứ bị lỗi trong phương pháp CreateQuery vì nó đi trong chuỗi và không phải là một lĩnh vực

IQueryable<S> IQueryProvider.CreateQuery<S>(System.Linq.Expressions.Expression expression) 
    { 
     if (typeof(S) != typeof(Field)) 
      throw new Exception("Only " + typeof(Field).FullName + " objects are supported."); 

     this._expression = expression; 

     return (IQueryable<S>)this; 
    } 

đây là truy vấn LINQ tôi sử dụng ... c olumnFilterList là Danh sách và các trường là lớp FieldCollection tùy chỉnh của tôi ở trên.

foreach (var name in columnFilterList) 
    { 
     var fieldName = (from x in fields where x.Name == name select x.Name).First 
    } 

.... Tôi chắc chắn rằng nó là một sai lầm đơn giản ... ai đó có thể cho tôi biết những gì tôi đang làm sai ... nhờ

Trả lời

3

Nếu bạn muốn một đối tượng để được sử dụng bởi LINQ, thực hiện IEnumerable<T>. IQueryable<T> là quá mức cần thiết cho LINQ to Objects. Nó được thiết kế để chuyển đổi các biểu thức thành dạng khác.

Hoặc nếu bạn muốn, bạn có thể làm điều này

FieldCollection someFieldCollection = ... 
IEnumerable<Field> fields = someFieldCollections.Cast<Field>(); 
+0

Đó chính xác là những gì tôi cần. Tôi đã cố gắng để suy nghĩ về vấn đề. Cảm ơn bạn! – user2810977

+0

và sắp xếp chúng theo tên: trường.OrderBy (f => f.Name) –

0

Trong trường hợp của bạn của gói và xây dựng một lớp xung quanh một loại sưu tập IEnumerable hiện nghĩa List<Field>,

bạn chỉ có thể sử dụng một bộ " chức năng chuyển tiếp" giấy gói mà phơi bày giao diện IQueryable<Field>:

public class WorkItemFieldCollection : IEnumerable<Field>, IQueryable<Field> 
{ 
    ... 
    #region Implementation of IQueryable<Field> 

    public Type ElementType 
    { 
     get 
     { 
      return this._fieldList.AsQueryable().ElementType; 
     } 
    } 

    public Expression Expression 
    { 
     get 
     { 
      return this._fieldList.AsQueryable().Expression; 
     } 
    } 

    public IQueryProvider Provider 
    { 
     get 
     { 
      return this._fieldList.AsQueryable().Provider; 
     } 
    } 

    #endregion 
    ... 
} 

bạn bây giờ có thể trực tiếp truy vấncủa bạn 0:

var workItemFieldCollection = new WorkItemFieldCollection(...); 
var Fuzz = "someStringId"; 
var workFieldItem = workItemFieldCollection.FirstOrDefault(c => c.Buzz == Fuzz); 
Các vấn đề liên quan