2013-09-24 3 views
6

VS2010 용 TFS API를 사용하고 있으며 FieldCollection을 쿼리하여 LINQ에서 지원하지 않는다고 가정하므로 Field 및 FieldCollection을 LINQ로 쿼리 할 수 ​​있도록 사용자 지정 클래스를 만들려고했습니다. 나는 기본 템플릿을 발견하고 컴파일 것처럼 그것을사용자 지정 클래스 만들기 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 
} 

을 구현하기 위해 노력하고 LINQ 인식했지만, 난 그것이 문자열에 통과하지 필드 때문에 CreateQuery 방법에 오류가 계속

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

여기 내가 사용하는 Linq 쿼리입니다 ... c olumnFilterList는 List이고 필드는 위의 사용자 정의 FieldCollection 클래스입니다.

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

가 .... 나는 확실히 그것을 단순한 실수 ... 누군가가 당신이 객체가 LINQ로 사용할 수 있도록하려면 감사

답변

3

구현 ... 잘못 뭐하는 거지 말해 수 IEnumerable<T>. IQueryable<T>은 LINQ to Object에 과도 함입니다. 표현을 다른 형식으로 변환하기 위해 설계되었습니다.

또는 당신이 원한다면, 당신은 포장의 귀하의 경우에는이

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

정확히 내가 필요한 것입니다. 나는 그 문제를 생각하려고 애 쓰고 있었다. 고맙습니다! – user2810977

+0

을 입력하고 이름순으로 정렬하려면 fields.OrderBy (f => f.Name) –

0

을하고 List<Field> 즉, 기존의는 IEnumerable 컬렉션 유형 주위에 클래스를 구축 할 수

당신은 단지 "의 집합을 사용할 수 있습니다 앞으로 기능 "는 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 
    ... 
} 

이제 직접를 조회 할 수 있습니다 0 :

var workItemFieldCollection = new WorkItemFieldCollection(...); 
var Fuzz = "someStringId"; 
var workFieldItem = workItemFieldCollection.FirstOrDefault(c => c.Buzz == Fuzz);