这个业务逻辑是否在我的视图模型中,是否允许?

时间:2015-02-13 09:14:56

标签: c# wpf mvvm

我有一个必须始终启动的WCF服务,因此由Windows服务托管。我的Windows服务模型具有简单的启动代码:

HostService:

public void StartService()
{
    if (_hostController.Status != ServiceControllerStatus.Stopped && _hostController.Status != ServiceControllerStatus.StopPending)
    {
        var msg = string.Format("Service '{0}' must be in status '{1}' or '{2}' to accept a 'Start' command.",
            HostResources.ServiceName, ServiceControllerStatus.Stopped, ServiceControllerStatus.StopPending);
        throw new HostServiceException(msg, HostServiceException.HostServiceExceptionCategory.ServiceStatusControl);
    }
    try
    {
        _hostController.Start();
    }
    catch (Exception ex)
    {
        if (ex is Win32Exception || ex is InvalidOperationException)
        {
            throw new HostServiceException(string.Format("'{0}' failed to respond properly to a 'StartService` command: '{1}'", _hostController.ServiceName, ex.Message), ex);
        }
        throw;
    }
    try
    {
        _hostController.WaitForStatus(ServiceControllerStatus.Running, _waitForStatusTimeout);
    }
    catch (TimeoutException tx)
    {
        throw new HostServiceException(string.Format("{0} did not start respond after {1} seconds and the 'Start' command timed out.", _hostController.ServiceName, _waitForStatusTimeout.TotalSeconds), tx);
    }
    if (ServiceControllerStatus.Running != _hostController.Status)
    {
        throw new HostServiceException(string.Format("The 'StartService' command for '{0}' failed. The Service has a status of '{1}'.", _hostController.ServiceName, _hostController.Status));
    }
}

我的WCF服务甚至更简单的启动代码:

SchedulerService:

public void Start()
{
    _isBusy = false;
    var interval = _config.Settings.ServicePollingInterval * 1000;
    _pollTimer = new Timer(interval);
    _pollTimer.Enabled = true;
    _pollTimer.Elapsed += PollTimerElapsed;
    _pollTimer.Start();
    Status = SchedulerServiceStatus.Running;
    var msg = string.Format("'{0}' started with the timer set for {1} second{2} intervals.", SchedulerResources.ServiceName, _pollTimer.Interval / 1000, _pollTimer.Interval / 1000 > 1 ? "s" : "");
    _logger.Info(msg);
    StatusChanged(this, new SchedulerStatusChangeEventArgs(Status, msg));
}

这是我的视图模型中的代码,因为只有它可以启动Windows服务,它才会启动WCF服务:

SchedulerViewModel:

private void ExecuteStart()
{
    if (_hostModel.ServiceStatus != ServiceControllerStatus.Running)
    {
        _logger.Warn("The '" + _hostModel.ServiceName + "' host service is not running. The '" + GetType().Name + "' will attempt to start it.");
        try
        {
            _hostModel.StartService();
        }
        catch (Exception ex)
        {
            var msg = string.Format("The '{0}' could not start the '{1}' host service: {2}", GetType().Name, _hostModel.ServiceName, ex.Message);
            _logger.Error(msg, ex);
            throw new HostServiceException(msg, HostServiceException.HostServiceExceptionCategory.ServiceController, ex);
        }
    }
    try
    {
        _scheduler.Start();
    }
    catch (Exception ex)
    {
        throw new SchedulerServiceException(ex.Message, SchedulerServiceException.SchedulerServiceExceptionCategory.SchedulerControl, ex);
    }
    SchedulerStatus = _scheduler.Status;
    CommandsCanExecuteChanged();
}

现在这确实不是视图逻辑,但它也不是业务逻辑;更像是家务:如果开启供水,我只能使用洗衣机。现在我并没有真正看到需要一个只有HostModelSchedulerService实例的全新模型,只是为了这个决定。陪审团对我目前的安排有什么看法?

1 个答案:

答案 0 :(得分:0)

我会将所有代码推送到另一个服务后面并通过接口将其注入到VM中,我这样做是因为我假设WCF通过事件公开状态并且你想在UI中显示它。如果你把它推到另一个服务之后,允许将暴露状态“塑造”成一个更适合在VM中使用的以UI为中心的模型。

如果你这样做了,从虚拟机的角度来看,所有它都会知道'start \ stop'方法和一个事件处理程序 - 然后将实现抽象掉,并通过模拟很容易地测试VM。 / p>

为了更进一步,我会考虑使用Reactive扩展而不是CLR事件来传达服务中的状态更改。