注意:请重新标记和/或重新命名
我有一个类FooEnumerator
,它包装了一个Foo
并实现了IEnumerable<FooEnumerator>
。 Foo
表示树状数据结构,枚举的FooEnumerator
是当前节点的子节点。Foo
是供应商提供的数据对象。 FooEnumerator
实现了一堆自定义过滤代码。
class FooEnumerator : IEnumerable<FooEnumerator>
{
public Foo WrappedNode { get; private set; }
public string Name { get { return WrappedNode.Name; } }
public int Id { get{ return WrappedNode.Id; } }
public DateTime Created { get{ return WrappedNode.Created; } }
public FooEnumerator(Foo wrappedNode)
{
WrappedNode = wrappedNode;
}
public IEnumerator<FooEnumerator> GetEnumerator()
{
foreach (Foo child in this.GetChildren())
if(FilteringLogicInHere(child))
yield return new FooEnumerator(child);
}
...
}
我希望能够使用给定的(任意)表达式对树的每个级别进行排序,这些表达式在创建顶级
FooEnumerator
时定义,并将该表达式传递给每个新枚举的项目以供使用。我想使用lambda定义排序表达式,就像使用OrderBy函数一样。实际上,我打算将lambda传递给
OrderBy
。OrderBy的签名为
OrderBy<TSource, TKey>(Func<TSource, TKey> keySelector)
其中,
TKey
是给定Func
的返回类型,但是是方法签名中的类型参数,并在编译时确定。用法示例
var x = GetStartingNode();
var sort = n => n.DateTime;
var enu = new FooEnumerator(x, sort);
var sort2 = n => n.Name;
var enu2 = new FooEnumerator(x, sort2);
然后将排序表达式存储在类变量中,而
FooEnumerator
的工作方式如下:// pseudo-implementation
private Expression<Func<Foo, TKey>> _sortBy;
public FooEnumerator(Foo wrappedNode, Expression<Func<Foo, TKey>> sortBy)
{
WrappedNode = wrappedNode;
_sortBy = sortBy;
}
public IEnumerator<FooEnumerator> GetEnumerator()
{
foreach (Foo child in this.GetChildren().OrderBy(_sortBy))
if(FilteringLogicInHere(child))
yield return new FooEnumerator(child);
}
在这种用例中,如何指定TKey的类型(隐式或显式)?
我不想对其进行硬编码,因为我希望能够对基础
Foo
的所有属性进行排序。 最佳答案
好的,您不能创建类型为Expression<Func<Foo,TKey>>
的成员委托变量,因为从未指定TKey
。但是,您可以创建一个Expression<Func<Foo,IComparable>>
类型的成员,该成员可以满足您的目的。当然,您可能需要更改FooEnumerator
构造函数以接受此签名。
编辑:其他人建议参数化您的FooEnumerator
,以便它接受TKey
。您当然可以这样做,但是您应该意识到出现的问题:
通过对枚举器进行参数设置,您便可以轻松完成工作。任何要存储FooEnumerator<T>
的代码都必须具有T
类型的先验知识。但是,您可以实现一个非通用接口IFooEnumerator
来处理该问题。
如果希望将来支持对多个字段进行排序,则对枚举器进行参数设置会产生问题。 C#不支持带有可变数量的类型参数的泛型,这限制了需要多个任意类型的泛型的创建。这个问题很难处理,因为开始创建FooEnumerator<T>
,FooEnumerator<T1,T2>
,FooEnumerator<T1,T2,T3...>
等很麻烦。