在 WPF/MVVM 应用中加载配置文件/处理启动时的错误



免责声明:我没有 MVVM/MVC/MVP/MV 的经验,这是我第一次尝试使用任何 UI 分离模式。

启动时,我的应用需要从配置文件加载数据,这是应用程序工作所必需的。

目前,我正在App.xaml.cs启动时读取配置文件,并将文件的内容传递给视图模型:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        string configFile = "settings.txt";
        string[] config = File.ReadAllLines(configFile);
        var window = new MainWindow();
        var viewmodel = new MainWindowViewModel(config);
        window.DataContext = viewmodel;
        window.Show();
    }
}

1. 这是"正确"的 MVVM 方式吗?我确信这种方式比直接在视图模型中读取文件更好(这就是我首先这样做的方式),但我不确定App.xaml.cs是否是读取配置文件的正确位置。

2. 我在哪里/如何处理错误?配置文件中的数据对于应用程序至关重要.
因此,如果文件丢失或为空,或者文件中的数据无效,那么我需要显示错误消息并退出应用程序。

我的第一个尝试是把它也放在App.xaml.cs

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        string configFile = "settings.txt";
        if (!File.Exists(configFile))
        {
            MessageBox.Show("config file missing");
            Application.Current.Shutdown();
            return;
        }
        string[] config = File.ReadAllLines(configFile);
        if (config.Count() == 0)
        {
            MessageBox.Show("config file empty");
            Application.Current.Shutdown();
            return;
        }
        var window = new MainWindow();
        var viewmodel = new MainWindowViewModel(config);
        window.DataContext = viewmodel;
        window.Show();
    }
}

但这对我来说看起来并不"正确"。我已经对在那里加载文件感到不舒服(请参阅第一个示例),所以这更糟。

注意:我知道我可能不应该在这里直接拨打Messagebox.Show.
请注意,这不是我在这里要问的 - 我知道我应该用更像 MVVM 的东西替换它,但重点是:我仍然必须从某个地方调用它(然后关闭应用程序).
我真正想知道的是App.xaml.cs是否是合适的地方!

3.另外,我还有另一种错误要处理:
配置文件的实际解析由模型完成(模型是现有库的一部分,我在这里构建的 WPF 应用程序只是一个不错的 UI).
因此,视图模型会创建模型的实例并调用解析方法...如果配置文件中的数据无效,则会引发异常。

我该如何以"MVVM 方式"处理此问题?
只是在视图模型中捕获异常并从那里关闭整个应用程序对我来说感觉不对。

<小时 />

编辑:

要回答威尔关于为什么我不使用app.config的评论:

我正在使用一个"特殊"配置文件,因为我需要从那里加载几个命名的值对"集"。下面是一个示例文件.
基本上,这是一个Dictionary<string, List<ClassWithTwoStringProperties>>

  1. AFAIK,app.config不支持这样的数据,所以我唯一能做的就是将整个事情保存为 app.config 中的一个属性中的 blob,并且仍然自己进行解析.
    -->所以我仍然必须从 WPF 应用程序中的某个位置调用解析。
  2. 我想要一种简单的、人类可编辑的格式
  3. WPF 应用程序只是一个不错的库 UI,我也需要在库中提供一个配置文件
我认为

这种方式是不正确的。

您应该将app.config视为任何持久化的数据(例如数据库、文件)。如果要以 MVVM 方式访问持久化的数据,则应编写一个服务(类似于 IApplicationDataService ),并从MainWindowViewModel代码调用此服务实现。如果您从某些ServiceLocator找到此服务或通过 IoC 容器注入它,它将更加 MVVMish——这有助于稍后编写单元测试。

服务的实现应返回视图模型初始化的模型实例。像这样:

public ApplicationDataService : IApplicationDataService
{
  public ApplicationModel LoadApplicationData()
  {
      // process app.config here
  } 
}
public ViewModelBase<TModel>
{
  public TModel Model
  {
    get { return model.Value; }
  }
  private readonly Lazy<TModel> model = new Lazy(GetModel);
  protected abstract TModel GetModel();
}
public MainWindowViewModel<ApplicationModel> : ViewModelBase
{
   protected override ApplicationModel GetModel()
   {
      try
      {
        var dataService = ServiceLocator.GetService<IApplicationDataService>();
        return dataService.LoadApplicationData();
      }
      catch (AnyException e)
      {
         // oops!
      }
   }
}

最新更新