繁体   English   中英

在单个元素级别应用Linq Func <T,TResult>键选择器

[英]Apply Linq Func<T, TResult> key selector at single element level

对不起,如果标题有误导性,不知道如何描述这个。

我的最终目标是使用IQueryable<T>的扩展方法和表达式的某种形式(见下面的例子),这将允许我必须返回包含原始TIQueryable<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM