2011-06-20 70 views
6

任何人都可以爲長流程的報告/監控狀態/進度提供良好的設計模式。 基本上,我有接收到一個「數據上下文」對象代碼庫:用於報告/監控長流程進度的設計模式

public class DataContext : IDataContext 
{ 
    pulbic Dictionary<string, objects> Properties { get; private set; } 

    // Additional properties removed for simplicity... 
} 

基於所提供的上下文,將創建一個任務(未TPL-任務)對象,與各子任務。 在執行過程中,DataContext對象被傳遞給各種可以檢索或更新它的子任務。

例如,假設主要任務是「複製文件」任務。 DataContext將具有諸如SourceFolder和TargetFolder的屬性,並且可能具有FilterFiles屬性(例如* .docx)。我們的主要任務將是一個CopyFilesTasks,它將有一個子流程的「管道」 - 掃描文件夾,掃描文件,篩選文件,複製文件等...

我在找什麼,是最好的方法以允許任務/子任務向呼叫者/執行者報告他們的進度。 在我們上面的例子中,進展中的變化可能只是「複製文件ABC.docx ...」,或者可能是更復雜一些的東西,比如「掃描文件夾XYZ ...」

我已經考慮過下列選項:

  1. INotifyPropertyChanged的:添加一個 「進步」 屬性的DataContext

    公共字符串進展{獲得;設置{_progress = value; RaisePropertyChanged( 「進度」); }

    並具有創建DataContext對象註冊到PropertyChanged事件的代碼。然而,這似乎是一個過於簡單化的做法...

  2. 的ILog(使用任何日誌框架您喜歡):在各種任務/子任務使用ILog的實例,有主要任務劊子手將它自己的監聽器添加到日誌框架中。然而,這似乎是彎曲日誌記錄機制來做它不應該做的事情。

  3. 烏迪大漢的DomainEvents:任務的劊子手可以把DataContext的一個「域」,因此,我們可以嘗試實行「事件處理程序」的「ProgressChanged」事件。從理論上講,這甚至可以用於更精細的事件,是發生在特定的子任務......但再一次,感覺就像強迫觀念......

我的關注點包括了諸如:

  • 進度可能不是唯一需要監控的「事件」 - 在我們上面的示例中,我們可能需要更多的定義,比如FolderHandled,FileCopied等,但我們可能不知道執行時的確切事件任務(記住 - 子任務是基於DataContext創建的,並可能導致執行不同的任務)。
  • 運行任務的上下文尚未定義。目前,我只是計劃從命令行應用程序運行任務,因此需要輸出到命令行進行調試。稍後,當我將其移至某個服務時,我可能希望讓一個「偵聽程序」用任務的進度更新數據庫(例如)。

回答

1

你可以聲明爲每個可能的操作類型參數,說FileOperationEventArgs文件操作,數據庫操作等

public class FileOperationEventArgs : EventArgs 
{ 
    public readonly string SourceFolder; 
    public readonly string TargetFolder; 

    public FileOperationEventArgs(string sourceFolder, string targetFolder) 
    { 
     SourceFolder = sourceFolder; 
     TargetFolder = targetFolder; 
    } 
} 

public class DatabaseUpdateEventArgs : EventArgs 
{ 
    public readonly int RowsUpdated; 

    public DatabaseUpdateEventArgs(int rowsUpdated) 
    { 
     RowsUpdated = rowsUpdated; 
    } 
} 

OperationProgress類聲明爲每個操作類型的事件DatabaseUpdateEventArgs。

public class OperationProgress 
{ 
    public event EventHandler<FileOperationEventArgs> FileCopied; 
    public event EventHandler<DatabaseUpdateEventArgs> DatabaseUpdated; 

    public void OnFileCopied(FileOperationEventArgs a) 
    { 
     if(FileCopied != null) 
      FileCopied(this, a); 
    } 

    public void OnDatabaseUpdated(DatabaseUpdateEventArgs a) 
    { 
     if (DatabaseUpdated != null) 
      DatabaseUpdated(this, a); 
    } 
} 

OperationProgress將在創建DataContext時指定。

public class DataContext : IDataContext 
{ 
    public Dictionary<string, object> Properties { get; private set; } 
    public OperationProgress Progress { get; private set; } 

    public DataContext(OperationProgress progress) 
    { 
     Progress = progress; 
    } 
} 

子任務執行可以更新進度。

public class FileCopySubTask 
{ 
    public void Execute(DataContext context) 
    { 
     context.Progress.OnFileCopied(new FileOperationEventArgs("c:/temp1", "c:/temp2")); 
    } 
} 
+0

這與Udi Dahan的DomainEvents類似,但更受限制 - 它僅限於特定「已知」事件的事件 - 我會必須在新事件發生時使用新事件編譯所有內容......這也意味着如果我有多個任務和多個「偵聽器」,我將不得不管理事件註冊/註銷和引用...... – SaguiItay