2014-02-18 88 views
2

我有一个类Bookstore,它实现了一个接口IBookstore通过接口搜索列表

Bookstore具有作为私有财产的图书列表:private List<Book> AllBooks;

我不想通过接口暴露的书籍的完整列表。相反,我希望用户根据某些属性查询图书。所以,在IBookstore我有以下几点:

public interface IBookstore 
{ 
    IList<Book> SelectedBooks; 
} 
public class Bookstore : IBookstore 
{ 
    private List<Book> AllBooks; 
    public IList<Book> SelectedBooks { get; set; } 
} 

我希望做的是创建一个名为SearchBooks的方法,将搜索包含各种属性的所有条目列表AllBooks,然后设置SelectedBooks与结果。所以,我使用的是以下几点:

Bookstore myStore = new Bookstore(); 
... 
myStore.SearchBooks(A BUNCH OF CRITERIA); 
myStore.SelectedBooks; // contains books selected by the criteria passed to SearchBooks above 

为什么我想这样做:

  • 我将需要访问SelectedBooks多次。我不想 多次运行搜索。
  • 我希望SelectedBooks的列表属于myBookstore。此对象只创建一次并在很多地方使用,所以我希望能够在许多地方访问相同的SelectedBooks,而无需重新构建它。将其作为当地财产存储是不可取的;即,我不想做List<Book> myBooks = myStore.SearchBooks(A BUNCH OF CRITERIA);。我有一个很好的理由。

我的问题

鉴于Book有很多特性,例如Title,Author,Date等,什么是最简单的方法任意通过一组搜索条件SearchBooks,以便我可以在Bookstore私人搜索我的列表?

例如,如果我有权访问应用程序中的整个列表,我可以使用Linq。我可以传递一个Linq查询到一个方法并让查询在myBookstore内私下执行吗?

+0

您是否考虑过按条件缓存搜索结果?如果内存不用担心,那么只需从'SearchBooks(...)'方法返回结果即可。 – Aaron

+0

@Aaron是的。我不想这样做。 – Emily

+0

我不想缓存结果的原因是因为我正在编写Unity3D的代码,并且在Unity中,我可以创建一个对象的实例并使其在多个级别和多个GameObjects中保持不变。如果我在查询结果时缓存了结果,那么结果会被限定在创建它们的GameObject中,如果我想将它们来回传递给其他GameObjects,那么我必须编写控制逻辑,或者我有重新执行查询。我宁愿将结果保存在'myBookstore'中,因为我可以在任何地方访问结果,而无需做任何额外的工作。 – Emily

回答

4

我可以将Linq查询传递给方法并让查询在myBookstore中私下执行吗?

您可以通过委托:

public void SearchBooks(Func<IEnumerable<Book>, IEnumerable<Book>> query) 
{ 
    SelectedBooks = query(AllBooks).ToList(); 
} 

调用示例:

myStore.SearchBooks(c => c.Where(b => b.Title == "test" && b.Author == "author")); 

或只是一组谓词:

public void SearchBooks(params Func<Book, bool>[] predicates) 
{ 
    var query = AllBooks.AsEnumerable(); 
    foreach(var p in predicates) 
     query = query.Where(p); 

    SelectedBooks = query.ToList(); 
} 

调用示例:

myStore.SearchBooks(x => x.Title == "test", x => x.Author == "author"); 
+0

为什么他只是在方法内部进行查询?有什么特别的理由 – marko

+0

@marko是的,因为我想将结果存储在'myBookstore'中。我希望作为myBookstore的一个属性来获取最近执行的查询所产生的书籍列表。 – Emily

+0

Marcin,谢谢,我相信这正是我需要的。不过,我不太了解如何使用它。我将如何构造论据? – Emily

0

我个人不会经历所有尝试抽象查询的概念的麻烦。相反,直接在图书清单上使用LINQ。

您可以将书目列表作为可枚举序列公开。

public interface IBookstore 
{ 
    IEnumerable<Book> Books; 
} 

然后你可以通过任何你喜欢的方式通过LINQ查询它。

IBookstore store; // Some store. 
var johngreenBooks = from book in store.Books 
        where book.Author == "John Green" 
        orderby book.Title 
        select book; 

如果您不想在每次枚举时评估查询,请将其设置为列表或数组。

var johngreenBookArray = johngreenBooks.ToArray(); 

您可以传递这个数组(或列表),也可以将它放在某处。在我看来,我用来选择某些书籍的查询与书店无关,因此我不会将结果存储在商店中。