2012-08-01 61 views
0

我是延遲執行和所有爵士樂的忠實粉絲,但現在我得到了稍微不同的問題。延期執行vs延期**數據來源**評估

考慮下面的第一天真的實現過程監控的,僅僅顯示由開始時間排序的當前計算機上運行的所有進程:

public partial class ProcessesByStartTimeForm : Form { 

    // ... init stuff 

    public static readonly IEnumerable<object> ProcessQuery 
     = from p in Process.GetProcesses() 
      let startTime = Eval.TryEvalOrDefault<DateTime?>(() => p.StartTime) 
      orderby startTime 
      select new { 
       Process = p.ProcessName, 
       StartTime = startTime, // could be null 
       Title = p.MainWindowTitle 
      }; 

    private void ProcessesByStartTimeForm_Load(object sender, EventArgs e) { 
     this.RefreshDataSource(); 
    } 

    private void refreshToolStripMenuItem_Click(object sender, EventArgs e) { 
     this.RefreshDataSource(); 
    } 

    private void RefreshDataSource() { 
     this.gridView.DataSource = ProcessQuery.ToList(); 
    } 
} 

(注:Eval.TryEvalOrDefault<T>(Func<T> f)僅僅是我用一個輔助方法評估可能會拋出異常的東西,並返回default(T))。

現在的事情是數據源只被計算一次,恰好在查詢的形成。

是的,我知道,我可以將這個查詢定義包裝在一個不斷重複創建的方法中,但我認爲你可以得到我的觀點是要得到某種整潔的技巧來進行評估數據源動態,每次查詢執行。

回答

0

HA ......我想我們可以應用與let子句中相同的技巧......定義一個在運行時也計算Func<IEnumerator<T>>的包裝器!

public partial class ProcessesByStartTimeForm : Form { 

    // ... init stuff 

    public static readonly IEnumerable<object> ProcessQuery 
     = from p in new DeferredEnumerable<Process>(() => Process.GetProcesses()) 
      let startTime = Eval.TryEvalOrDefault<DateTime?>(() => p.StartTime) 
      orderby startTime 
      select new { 
       Process = p.ProcessName, 
       StartTime = startTime, // could be null 
       Title = p.MainWindowTitle 
      }; 

    class DeferredEnumerable<T> : IEnumerable<T> { 
     readonly Func<IEnumerable<T>> f; 

     public DeferredEnumerable(Func<IEnumerable<T>> f) { 
      this.f = f; 
     } 

     public IEnumerator<T> GetEnumerator() { 
      return this.f().GetEnumerator(); 
     } 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { 
      return this.GetEnumerator(); 
     } 
    } 
}