我有为长时间运行的任务设计的视图。它有一个标题和一个进度条。因此,该模型具有标题文本、进度条计数器和 TotalAmountOfWork 字段。该模型还具有
public delegate void TaskCompleted(string resultDescription);
public event TaskCompletedCopyingCompletedEvent;
public event Action UpdateViewState;
当计数器改变时,模型调用 UpdateViewState。ViewModel 订阅了事件并在它的视图中更新。
好的。我有两个类用于将文件从硬盘复制到闪存驱动器和一个用于诊断信息检索的类,这些信息最终也应该复制到闪存驱动器。
我想在同一个 ViewModel 中使用它们,但我不知道如何避免代码重复。我不知道如何依靠正确的面向对象设计来实现它。
这三个类可以实现这样的接口:
interface ILongRunningTask {
void DoWork();
}
然后我可以实现 ViewModel 以 ILongRunningTask 作为参数。
但是看名称的接口名称。看起来太笼统了。这样的抽象似乎有问题。
好的。在我看来,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
}
}
}
这两个类使用“复制”作为方法的名称。现在我想再添加一个行为非常相似的类,但它的方法似乎应该命名为“CollectDiagnosticInfo”。或者,也许我可以添加一个类 DiagnosticInfoCopier:IFilesCopier,然后做同样的事情。我真的不知道,但第六感暗示有某种气味。