gpt4 book ai didi

c# - 制作自定义类 IQueryable

转载 作者:太空狗 更新时间:2023-10-29 17:56:16 26 4
gpt4 key购买 nike

我一直在使用 VS2010 的 TFS API,不得不查询我发现 LINQ 不支持的 FieldCollection,所以我想创建一个自定义类来使 LINQ 可以查询 Field 和 FieldCollection,所以我找到了一个基本模板并尝试实现它

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 查询...columnFilterList 是 List,fields 是我的自定义 FieldCollection 类,见上文。

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

....我确定这是一个简单的错误...有人可以告诉我我做错了什么...谢谢

最佳答案

如果您希望 LINQ 可以使用一个对象,请实现 IEnumerable<T> . IQueryable<T>对于 LINQ to Objects 来说太过分了。它旨在将表达式转换为另一种形式。

如果你愿意,你可以这样做

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

关于c# - 制作自定义类 IQueryable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18982108/

26 4 0