是否可以从默认构造函数反序列化为'this'?



情况:

我有一个绑定到设置视图的ViewModel,在该视图中,用户应该输入许多个性化设置,并且应该能够将其保存为预设并加载它们。为此,ViewModel拥有预设数据模型的集合,它们本身拥有不同的属性,类对象等。该计划是通过XML序列化和整个ViewModels的避免序列化来实现所有预设。

代码/问题

我从viewModel的构造函数中称为以下方法:

private void InitializePresetsFromFile()
{
    if (!File.Exists(Info.GetDefaultColorPalettePresetsXml()))
    {
        SetupNewEmpty();
        SerializePresets(Info.GetDefaultColorPalettePresetsXml());
    }
    else
    {
        DeserializePresets(Info.GetDefaultColorPalettePresetsXml());
    }
}

因此,该方法检查保存预设的文件是否存在 - 如果不存在,则应设置一个空预设并将其保存到新创建的文件中,否则应从现有文件中加载预设。

序列化过程效果很好,但是由于我序列化与this序列化,因此存在问题:

private void DeserializePresets(string path)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(LinearAxisColorPresetsViewModel));
    TextReader reader = new StreamReader(path);
    object obj = deserializer.Deserialize(reader);
    LinearAxisColorPresetsViewModel XmlData = (LinearAxisColorPresetsViewModel)obj;
    reader.Close();
    VolumePresetList = XmlData.VolumePresetList;
    WaveShapePresetList = XmlData.WaveShapePresetList;
    VolumePresetSelectedIndex = XmlData.VolumePresetSelectedIndex;
    WaveShapePresetSelectedIndex = XmlData.WaveShapePresetSelectedIndex;
}

这里的问题是,由于我直接从构造函数调用方法InitializePresetsFromFile(),因此,Deserializer以永无止境的循环呼叫自己,导致堆栈流错误。

那么,最简单的解决方案应该是使用一个带有参数的构造函数,我称之为InitializePresetsFromFile(),对吗?这里的问题是,ViewModel类直接在相应视图的XAML中实例化:

<UserControl.Resources>
    <ResourceDictionary>
        <vm:LinearAxisColorPresetsViewModel x:Key="vm" />
    </ResourceDictionary>
</UserControl.Resources>

此文章第二个答案指出,惯例是,从XAML调用的构造函数应该是无参数的,我想坚持下去。

问题:

问题只是如何根据最佳实践解决这个问题。由于这是我第一次尝试序列化和挑选化的尝试,因此我担心我在这里有些错误的道路。我的感觉是只有数据模型类才能序列化。我的ViewModel拥有此类类的两个观测值,但是我想序列化完整的集合以及ViewModel中的其他属性,例如所选的索引。

您确实已经达到了必须决定如何继续的地步。您现在正在做的事情不起作用。在这种情况下,XML序列化器和XAML都使用默认构造函数。您不能在这里实现两个目的。

我的建议是创建一个类,该类反映您的视图模型的属性,您可以用来对XML文件进行验证。此类只需要属性,仅此而已。

如果视图模型类实际上是静态类,则可以使用定位器类将其绑定到。

首先,您不应该在类构造器中调用InitializePresetsFromFile方法。构造函数必须尽可能快,不应引起副作用。在构造函数中读取文件是一个不好的做法:您不能在不访问文件系统的情况下创建类的实例。这意味着您的代码不可测试,它是容易出错的(例如,您是否考虑过突然的UnauthorizedAccessException s?),并且很慢。

相反,创建一个公共方法,该方法可以从文件中估算数据。这将破坏您的无尽递归。

如何调用该方法?

  • 您真的需要在资源词典中使用LinearAxisColorPresetsViewModel实例吗?如果不是,只需将避难实例分配给视图的DataContext属性。
  • 如果确实需要,请在您的视图模型中创建ICommand,例如InitializeCommand使用上述方法从文件中初始化内部状态;在应用程序启动/视图上执行该命令等。您可以使用例如InvokeCommandActionLoaded事件。

最新更新