2010-12-02 43 views
1

我在使用IEnumerable和LINQ時遇到困難。也許我不完全理解它。LINQ問題難度

我有假文件(「PlumFile」)和一些過濾器的數據源。每個篩選器都有一個Fits(PlumFile),用於確定參數是否適合該篩選器。每個過濾器還有一個枚舉指示它是「和」,「或」還是「不」。

這裏是我怎樣,我想所有這些過濾器組合成一個查詢:

public ObservableCollection<PlumFile> FoundFiles 
    { 
     get 
     { 
      ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>(); 

      // get the data source 
      IEnumerable<PlumFile> query = PlumData.GetFiles(); 

      foreach (FilterConstraint filter in filters) 
      { 
       // debugging 
       IList<PlumFile> oldQuery = query.ToList(); 

       switch (filter.QueryCombiningRule) 
       { 
        case FilterConstraint.QueryRule.And: 
         query = query.Where(file => filter.Fits(file)); 
         break; 
        case FilterConstraint.QueryRule.Or: 
         query = query.Concat(PlumData.GetFiles().Where(file => filter.Fits(file))); 
         break; 

        // is this really how I want to do 'not'? 
        case FilterConstraint.QueryRule.Not: 
         query = query.Where(file => !filter.Fits(file)); 
         break; 
       } 

       // debugging 
       IList<PlumFile> currQuery = query.ToList(); 

      } 

      query = query.Distinct(); 

      foreach (PlumFile file in query) 
      { 
       searchResults.Add(file); 
      } 

      return searchResults; 
     } 
    } 

我不知道我在做什麼錯。對於某些查詢,它工作正常。對於其他人,它失敗了。

如果我有一個「和」過濾器,它工作正常。然後我添加一個「不」過濾器,該過濾器不應該過濾掉已經選擇的任何東西,但是一切都被刪除了。爲什麼是這樣?

(我這樣做是爲Silverlight 4應用程序,但我不認爲它很重要。)

更新

public class NameFilterConstraint : FilterConstraint 
{ 
    public string Name { get; set; } 

    public override bool Fits(PlumFile plumFile) 
    { 
     return plumFile.Name.Contains(Name); 
    } 

    public override string Description 
    { 
     get 
     { 
      return ToString(); 
     } 
    } 

    public override string ToString() 
    { 
     return String.Format("Name contains '{0}'", Name); 
    } 
} 

:過濾約束 一個例子更新2:這是一個非LINQ版本,沒有我前面提到的錯誤:

public ObservableCollection<PlumFile> FoundFiles 
     { 
      get 
      { 
       ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>(PlumData.GetFiles().ToList()); 

       foreach (FilterConstraint filter in filters) 
       { 
        switch (filter.QueryCombiningRule) 
        { 
         case FilterConstraint.QueryRule.And: 
          foreach (PlumFile file in searchResults.ToList()) 
          { 
           if (! filter.Fits(file)) 
           { 
            searchResults.Remove(file); 
           } 
          } 
          break; 

         case FilterConstraint.QueryRule.Or: 
          foreach (PlumFile file in PlumData.GetFiles()) 
          { 
           if (filter.Fits(file)) 
           { 
            searchResults.Add(file); 
           } 
          } 
          break; 

         case FilterConstraint.QueryRule.Not: 
          foreach (PlumFile file in searchResults.ToList()) 
          { 
           if (filter.Fits(file)) 
           { 
            searchResults.Remove(file); 
           } 
          } 
          break; 
        } 
       } 

       return new ObservableCollection<PlumFile>(searchResults.Distinct()); 
      } 
     } 

所以,我想我的問題已經解決了,儘管我仍然對LINQ的做法感到好奇。也許我的意圖(在最後一個例子中已經明確)沒有正確地轉換成LINQ?

+1

你可以包含適合Fits方法的代碼嗎? – Mark 2010-12-02 18:20:55

+0

我花了5分鐘盯着這個,但我的大腦傷害只是看着問題,因爲它:) – Contango 2010-12-02 18:21:53

+0

@Gravitas:是因爲我濫用LINQ?我怎樣才能以一種不太複雜的方式做到這一點? – 2010-12-02 18:38:15

回答

2

這裏只是一個猜測,但我不知道這是一個捕獲/封閉問題。試試這個:

public ObservableCollection<PlumFile> FoundFiles 
    { 
     get 
     { 
      ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>(); 

      // get the data source 
      IEnumerable<PlumFile> query = PlumData.GetFiles(); 

      foreach (FilterConstraint filter in filters) 
      { 
       var localFilter = filter; 
       // debugging 
       IList<PlumFile> oldQuery = query.ToList(); 

       switch (filter.QueryCombiningRule) 
       { 
        case FilterConstraint.QueryRule.And: 
         query = query.Where(file => filter.Fits(file)); 
         break; 
        case FilterConstraint.QueryRule.Or: 
         query = query.Concat(PlumData.GetFiles().Where(file => localFilter.Fits(file))); 
         break; 

        // is this really how I want to do 'not'? 
        case FilterConstraint.QueryRule.Not: 
         query = query.Where(file => !localFilter.Fits(file)); 
         break; 
       } 

       // debugging 
       IList<PlumFile> currQuery = query.ToList(); 

      } 

      query = query.Distinct(); 

      foreach (PlumFile file in query) 
      { 
       searchResults.Add(file); 
      } 

      return searchResults; 
     } 
    } 
1

表面上,我建議應用過濾器作爲急切的評價(不懶惰)。

使用.ToList()應用循環內部的所有過濾器+使「查詢」列表。 如果這不起作用,那麼你還需要發佈「適合」方法。