2011-12-14 21 views
10

Xin lỗi nếu tiêu đề gây hiểu lầm, không chắc chắn cách mô tả tiêu đề này.Áp dụng công cụ chọn LINQ Func <T, TResult> ở cấp phần tử đơn

mục tiêu cuối cùng của tôi là phải có một phương pháp mở rộng của IQueryable<T> và một số hình thức (xem dưới đây chẳng hạn) của biểu thức đó sẽ cho phép tôi phải trả lại một IQueryable<EntityIndex<T>> (hoặc tương tự), trong đó có bản gốc T trong lĩnh vực Entity và một mảng/ienumerable chứa các phần tử như được mô tả bởi một số dạng biểu thức.

Tôi biết rằng không thực sự có ý nghĩa, hy vọng nó sẽ sau một ví dụ ...

Đây là những gì tôi có cho đến nay:

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

Lưu ý: Trên đây không biên dịch, nó chỉ đơn giản là có để thử và hiển thị những gì tôi đang cố gắng để đạt được.

Tôi đã sử dụng chuẩn selector, nhưng tiểu một cách tối ưu, phải tùy tiện tạo ra một loạt các T về việc chuyển nhượng đối với tài sản 'Index' để có thể áp dụng bộ chọn. Tôi hy vọng một sự lựa chọn tốt hơn của tham số có thể giải quyết điều này, nhưng có thể không. Vấn đề chính là điều này không biên dịch vì vậy nếu có một tinh chỉnh nhỏ sẽ cho phép nó hoạt động tốt với tôi, nếu bạn có thể hiểu ngữ pháp của tôi và hiểu những gì tôi đang cố gắng làm, và xảy ra để biết một cách tốt hơn để đi về nó tôi sẽ được đánh giá rất cao.

Lý tưởng nhất, tôi cần giải pháp được hiểu bởi động cơ L2S, điều mà tôi không thuyết phục được ở trên là nhờ vào sự ra đời của lớp EntityIndex, nhưng tôi đang hy vọng rằng nó sẽ xử lý nó như một lớp vô danh.

EDIT:

Tốt điểm Damien, bức tranh lớn hơn có lẽ là dễ dàng hơn nhiều để mô tả ...

Tôi muốn một phương pháp mở rộng chấp nhận một biểu thức, khái niệm nên mô tả các trường trên thực thể để chỉ số, sẽ được sử dụng sau biểu thức cụ thể này để cho phép một tiêu chí (điều khoản) được áp dụng cho các trường đã chọn.

Câu chuyện dài, ở một số vị trí trong mã, chúng tôi có tìm kiếm chuỗi ký tự đại diện.Nếu tôi có một EntityA với Property1, Property2, Property3, vv, nó không phải là không phổ biến để xem mã như:

viết tay, xin vui lòng tha lỗi chính tả nhỏ

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

EDIT:

Tiếp tục làm rõ - sử dụng WildcardEarch ở trên làm ví dụ, những gì tôi đã hy vọng là có thể có công cụ chọn như sau hoặc tương tự:

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

Với một biểu hiện đầy đủ mô tả các trường trên thực thể để tìm kiếm, trả lại IQueryable<EntitySearch<T>> như trình bày ở trên, tôi hy vọng sẽ có thể áp dụng một tiêu chuẩn duy nhất, tương tự như:

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 
} 

Với phần mở rộng ở phía trên rất mà tôi không thể làm việc và logic tiêu chí này, tôi có thể lấy một số IQueryable<T>, chọn một số trường và áp dụng tìm kiếm ký tự đại diện thích hợp trên các trường, cuối cùng trả lại IQueryable<T> một lần nữa khi đã thêm bộ lọc.

Thanks¬!

hãy góp ý, nếu bạn cần thêm thông tin/làm rõ ...

EDIT: Fair một @subkamren và cảm ơn sự quan tâm. Một số ví dụ không chung chung có thể được sử dụng. Tôi sẽ soạn thảo một vài thứ và thêm chúng ngay. Trong thời gian này, một số làm rõ dựa trên nhận xét của bạn ...

Cho một số IQueryable<Animal> Tôi muốn tiện ích mở rộng cho phép tôi chọn các trường trên Động vật mà tôi định tìm kiếm/lập chỉ mục. Ví dụ: Animal.Description, Animal.Species.Name v.v. Tiện ích mở rộng này sẽ trả về một cái gì đó như là IIndexedQueryable<Animal>. Đó là vấn đề tôi đang cố giải quyết trong câu hỏi trên. Hình ảnh rộng hơn được đề cập, tôi rất hài lòng nếu bạn sẵn sàng trợ giúp, như sau:

Giao diện IIndexedQueryable<T> lần lượt Tôi muốn gia hạn có thể mất thời hạn tìm kiếm là string. Tiện ích phải giải quyết các ký tự đại diện trong cụm từ tìm kiếm, mở rộng IQuery gốc ban đầu với tiêu chí cần thiết để thực hiện tìm kiếm trên các trường được lập chỉ mục và trả lại một lần nữa là IQueryable<T>.

Tôi đánh giá cao việc này có thể được thực hiện trong một bước, nhưng tôi hy vọng sẽ thực hiện theo cách này để sau này tôi có thể xem xét thêm phương thức mở rộng thứ ba áp dụng cho IIndexedQueryable<T>. .. ^^ Có ý nghĩa gì không?

Đó là bức tranh lớn hơn ít nhất, câu hỏi này đề cập chủ yếu với việc có thể chỉ định các trường tôi nhắm mục tiêu để lập chỉ mục theo cách mà tôi có thể sử dụng chúng sau đó như đã đề cập ở đây.

+2

Tôi không chắc là tôi hiểu được nêu ra - có lẽ nếu bạn có thể đưa ra một ví dụ về cách phương pháp này sẽ được sử dụng * *, nó có thể là rõ ràng hơn (hoặc nếu điều này là một phần của giải pháp cho một vấn đề lớn hơn, có thể xác định vấn đề lớn hơn và xem liệu chúng ta có thể giải quyết điều đó một cách tốt hơn)? –

+0

@Damien_The_Unbeliever - công bằng một, tôi đã thêm một phần hình ảnh lớn hơn, hy vọng rằng sẽ giúp làm rõ mọi thứ một chút? Ý tưởng cho rằng phương pháp mở rộng mà tôi đang mắc kẹt và một phương thức khác tạo ra một biểu thức đầy đủ dựa trên vị trí ký tự đại diện, tôi có thể giảm tất cả các phiên bản trùng lặp của WildcardSearch với các phiên bản dựa trên chung/biểu thức có thể đọc được. Cảm ơn! – Smudge202

+1

Đã chuyển đổi thành C# để tiếp cận đối tượng rộng hơn – Smudge202

Trả lời

4

Vì vậy, một cái gì đó như:

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

Ghi nhận rằng EntityIndex quát Xác định với TIndexType (gọi tắt là Y ở đây) là rất quan trọng bởi vì bạn không biết trước những gì chỉ số này.Việc sử dụng một generic cho phép Y là một đếm, do đó những điều sau đây sẽ làm việc như một selector index:

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

EDIT (Thêm chi tiết hơn nữa):

Sử dụng ở trên, bạn có thể nhóm các kết quả theo Giá trị chỉ mục duy nhất:

var animalClassifications = animalsClassified 
           .SelectMany(ac => ac.IndexValue.Select(iv => new { IndexValue = iv, Entity = ac.Entity })) 
           .GroupBy(kvp => kvp.IndexValue) 

Điều tôi đã mô tả ở đây là (một dạng đơn giản hóa) thuật toán MapReduce được Google phổ biến rộng rãi. Một hình thức phân phối giống nhau thường được sử dụng để nhận dạng từ khóa trong tìm kiếm văn bản, nơi bạn muốn xây dựng chỉ mục (cụm từ tìm kiếm) -> (danh sách chứa tài liệu).

+0

nên không phải là được 'e => mới EntityIndex {Entity = e, IndexValue = indexSelector (e)}' trong mẫu mã rất đầu tiên ở trên? – afrischke

+0

Vâng, cảm ơn bạn đã nắm bắt. Đã chỉnh sửa cho phù hợp. –

+0

Vì một lý do nào đó mà tôi không được thông báo về @ChrisShain này, cảm ơn bạn rất nhiều. Tôi sẽ cho đi! – Smudge202

Các vấn đề liên quan