我有为长时间运行的任务设计的视图。它有一个标题和一个进度条。 因此,模型具有标题的文本和进度条和TotalAmountOfWork字段的计数器。该模型也有
public delegate void TaskCompleted(string resultDescription);
public event TaskCompletedCopyingCompletedEvent;
public event Action UpdateViewState;
当计数器更改时,模型会调用UpdateViewState。 ViewModel在视图中订阅了事件和更新。
确定。我有两个类用于将文件从硬盘复制到闪存驱动器,一个类用于诊断信息检索,这些信息最终也应该复制到闪存驱动器中。
我想在同一个ViewModel中使用它们,但我无法弄清楚如何避免代码重复。我无法弄清楚如何依靠适当的面向对象设计。
这三个类可以实现这样的接口:
interface ILongRunningTask {
void DoWork();
}
然后我可以将ILongRunningTask作为参数实现ViewModel。
但请查看界面名称。它看起来太笼统了。这样的抽象似乎有些不对。
确定。在我看来,ViewModel应该采用委托来调用长时间运行的任务。但在这种情况下,ViewModel将如何与更新其属性的模型进行交互?
//更新 现在,模型看起来像:
public class FilesCopyingModel : IFilesCopier {
protected int filesCountToCopy;
public int FilesCountToCopy {
get { return filesCountToCopy; }
set {
filesCountToCopy = value;
InvokeUpdateViewState();
}
}
protected int currentProgressValue;
public int CurrentProgressValue {
get { return currentProgressValue; }
set {
currentProgressValue = value;
InvokeUpdateViewState();
}
}
public delegate void CopyingCompleted(string resultDescription);
public event CopyingCompleted CopyingCompletedEvent;
public event Action UpdateViewState;
private readonly IFilesCopier filesCopier;
protected FilesCopyingModel() {
}
public FilesCopyingModel(IFilesCopier filesCopier) {
if (filesCopier == null)
throw new ArgumentNullException("filesCopier");
this.filesCopier = filesCopier;
}
protected static string GetCurrentDateTime() {
return DateTime.Now.ToString("dd.MM.yyyy hh.mm.ss");
}
protected void InvokeCopyCompletedEvent(string resultDescription) {
if (CopyingCompletedEvent != null)
CopyingCompletedEvent(resultDescription);
}
protected void InvokeUpdateViewState() {
if (UpdateViewState != null)
UpdateViewState();
}
protected DriveInfo GetFirstReadyRemovableDrive() {
return
DriveInfo.GetDrives()
.FirstOrDefault(driveInfo => driveInfo.DriveType == DriveType.Removable && driveInfo.IsReady);
}
public void Copy() {
filesCopier.Copy();
}
}
public interface IFilesCopier {
void Copy();
}
public class KFilesCopier : FilesCopyingModel, IFilesCopier {
private string destinationKFilesDirPath;
public new void Copy() {
//some code
}
private static string ComposeDestinationKFilesDirPath(DriveInfo drive) {
//some code
}
}
public class LogsDirCopier : FilesCopyingModel, IFilesCopier {
public readonly string LogsDirPath;
public LogsDirCopier() {
//some code
}
public new void Copy() {
//some code
}
private void InternalCopyLogsDir(string destinationPath) {
//some code
}
private static void CloseStorer(ZipStorer zipStorer) {
//some code
}
private static string ComposeDestinationArchiveFilePath(string destinationPath) {
//some code
}
private void DetermineLogFilesCount() {
//some code
}
ViewModel与上面的基础架构交互:
public class FilesCopyingViewModel: Screen {
private readonly FilesCopyingModel model;
private readonly IWindowManager windowManager;
public int CurrentProgress {
get { return model.CurrentProgressValue; }
}
public int FilesCountToCopy {
get { return model.FilesCountToCopy; }
}
[ImportingConstructor]
public LongRunningViewModel(IFilesCopier copier) {
model = copier as FilesCopyingModel;
model.CopyingCompletedEvent += CopyingCompletedHandler;
model.UpdateViewState += UpdateViewStateHandler;
windowManager = new WindowManager();
}
private void UpdateViewStateHandler() {
NotifyOfPropertyChange(() => CurrentProgress);
NotifyOfPropertyChange(() => FilesCountToCopy);
}
private void CopyingCompletedHandler(string resultDescription) {
//some code
}
private void RemoveDriveSafely() {
//some code
}
private void PromptEjection(string result) {
//some code
}
private void PromptSuccessEjection() {
//some code
}
private void PromptEjectFlashError() {
//some code
}
protected override void OnActivate() {
try {
var copier = (IFilesCopier) model;
Task.Factory.StartNew(copier.Copy);
}
catch (Exception ex) {
//error handling
}
}
}
这两个类使用“Copy”作为方法的名称。现在我想添加一个具有非常相似行为的类,但似乎它的方法应该被命名为“CollectDiagnosticInfo”。或者也许我可以添加一个类DiagnosticInfoCopier:IFilesCopier然后只是做同样的事情。我真的不知道,但第六感表明有某种气味。