[英]Apply Linq Func<T, TResult> key selector at single element level
对不起,如果标题有误导性,不知道如何描述这个。
我的最终目标是使用IQueryable<T>
的扩展方法和表达式的某种形式(见下面的例子),这将允许我必须返回包含原始T
的IQueryable<EntityIndex<T>>
(或类似)在Entity
字段中,以及包含由某种表达式描述的元素的数组/ ienumerable。
我知道这没有多大意义,希望它会在一个例子之后......
这是我到目前为止:
class EntityIndex<T, TKey>
{
T Entity { get; set; }
// Doesn't have to be IEnumerable, whatever is easier
IEnuermable<TKey> Index { get; set; }
}
static class Elsewhere
{
[Extension()]
public IQueryable<EntityIndex<T, TKey>> IndexBy<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey[]>> indexSelector)
{
return source.Select(n => new EntityIndex<T, TKey> {
Entity = n,
Index = new T[] { n }.Select(indexSelector)
});
}
}
注意:上面没有编译 ,它只是尝试显示我想要实现的目标。
我已经使用了标准选择器,但次优,不得不在“Index”属性的赋值上任意创建一个T
数组,以便能够应用选择器。 我希望更好的参数选择可以解决这个问题,但可能不会。 主要的问题是这不会编译,所以如果有一个小的调整,将允许它工作,我很好,如果你能理解我的胡言乱语,了解我正在尝试做什么,并碰巧知道一个更好的方法为此,我将非常感激。
理想情况下,我需要L2S引擎理解解决方案,我不相信上面是由于EntityIndex
类的引入,但我希望它将它视为一个匿名类。
编辑:
好点Damien,更大的图片可能更容易描述......
我想要一个接受表达式的扩展方法,该表达式应描述要索引的实体上的哪些字段,这些字段将在此特定表达式之后使用,以允许将标准(where子句)应用于所选字段。
长话短说,在代码中的很多地方我们都有一个通配符字符串搜索。 如果我有一个带有Property1,Property2,Property3等的EntityA,那么看到以下代码并不罕见:
手写,请原谅小错字
public string[] WildcardSearch(string prefixText, int count)
{
string searchTerm = prefixText.Replace(wildcard, string.Empty);
if (prefixText.StartsWith(wildcard) && prefixText.EndsWith(wildcard)) {
return entitySet.Where(n => n.Property1.Contains(searchTerm) || n.Property2.Contains(searchTerm)).Select(n => n.Property3).ToArray();
} else if (prefixText.StartsWith(wildcard)) {
return entitySet.Where(n => n.Property1.EndsWith(searchTerm) || n.Property2.EndsWith(searchTerm)).Select(n => n.Property3).ToArray();
// you get the picture, same with EndsWith, no wildcards defaults to contains...
}
}
编辑:
进一步澄清 - 以上面的WildcardEarch为例,我希望能够拥有如下选择:
Func<EntityA, IEnumerable<string>> indexSelector = n => new string[] {
n.Property1,
n.Property2
};
// Alternatively, a ParamArray of keySelector might work?
Func<EntityA, string>[] keySelectors = new Func<EntityA, string>[] {
n => n.Property1,
n => n.Property2
};
给出足够的表达式来描述要搜索的实体上的哪些字段,返回如上所示的IQueryable<EntitySearch<T>>
,我希望能够应用单个标准,类似于:
Func<EntitySearch<T>, bool> criterion = n => false;
if (wildcardIsContains) {
criterion = n => n.Values.Any(x => x.Contains(searchTerm));
} else if (wildCardIsStartsWith) {
criterion = n => n.Values.Any(x => x.Contains(searchTerm));
//etc
}
鉴于我无法工作的最顶层扩展,以及这个标准逻辑,我应该能够采用IQueryable<T>
,选择一些字段,并在字段上应用适当的通配符搜索,最后返回IQueryable<T>
再次添加了过滤。
Thanks¬!
如果您需要更多信息/说明,请发表评论......
编辑:公平的@subkamren并感谢您的兴趣。 一些非通用示例可能有用。 我会起草一些内容并很快添加它们。 目前,根据您的评论进行一些澄清......
给定一个IQueryable<Animal>
我想要一个扩展,允许我在Animal上选择我打算搜索/索引的字段。 例如, Animal.Description, Animal.Species.Name
等。此扩展应返回类似于IIndexedQueryable<Animal>
。 这是我在上面的问题中试图解决的问题。 如果您愿意提供帮助,我提到的更广泛的情况如下:
反过来,我想要一个IIndexedQueryable<T>
接口,我想要一个可以采用string
搜索术语的扩展名。 扩展应该解析搜索项中的通配符,使用必要的标准扩展原始IQueryable以对索引字段执行搜索,并再次返回IQueryable<T>
。
我很欣赏这可以在一个步骤中完成,但我希望这样做,以便稍后我可以考虑添加适用于IIndexedQueryable<T>
的第三个扩展方法,允许我使用SQL Server执行IIndexedQueryable<T>
搜索。 。^^有道理吗?
这至少是一个更大的图景,这个问题主要涉及能够指定我打算以这样的方式索引的字段,我可以在此后使用它们。
所以类似于:
public static IEnumerable<EntityIndex<T, Y>> IndexBy<T, Y>(this IEnumerable<T> entities, Func<T, Y> indexSelector) {
return entities.Select(e => new EntityIndex<T, Y> { Entity = e, IndexValue = indexSelector(e) });
}
注意到通常使用TIndexType定义EntityIndex(此处称为Y)很重要,因为您事先并不知道索引是什么。 泛型的使用允许Y为枚举,因此以下将用作索引选择器:
// Assuming Animal has attributes "Kingdom", "Phylum", "Family", "Genus", "Species"
// this returns an enumeration of EntityIndex<Animal, String[]>
var animalsClassified = someAnimals.IndexBy(a => new String[] { a.Kingdom, a.Phylum, a.Family, a.Genus, a.Species });
编辑(添加更多细节):
使用上面的内容,您可以按唯一索引值对结果进行分组:
var animalClassifications = animalsClassified
.SelectMany(ac => ac.IndexValue.Select(iv => new { IndexValue = iv, Entity = ac.Entity }))
.GroupBy(kvp => kvp.IndexValue)
顺便说一下,我在这里描述的是Google推广的MapReduce算法(一种非常简化的形式)。 分布式形式通常用于文本搜索中的关键字识别,您要在其中构建(搜索项) - >(包含文档的列表)的索引。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.