Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否无法反序列化到';这';从默认构造函数?_C#_.net_Serialization_Xml Serialization - Fatal编程技术网

C# 是否无法反序列化到';这';从默认构造函数?

C# 是否无法反序列化到';这';从默认构造函数?,c#,.net,serialization,xml-serialization,C#,.net,Serialization,Xml Serialization,情况: 我有一个绑定到设置视图的ViewModel,用户应该在其中输入大量个性化设置,并且应该能够将它们保存为预设并加载它们。为此,ViewModel包含预设数据模型的集合,这些数据模型本身包含不同的属性、类对象等。 计划是通过对整个ViewModels进行xml序列化和反序列化来实现保存所有预设 代码/问题 从ViewModel的构造函数中,我调用以下方法: private void InitializePresetsFromFile() { if (!File.Exists(Info

情况:

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

代码/问题

从ViewModel的构造函数中,我调用以下方法:

private void InitializePresetsFromFile()
{
    if (!File.Exists(Info.GetDefaultColorPalettePresetsXml()))
    {
        SetupNewEmpty();
        SerializePresets(Info.GetDefaultColorPalettePresetsXml());
    }
    else
    {
        DeserializePresets(Info.GetDefaultColorPalettePresetsXml());
    }
}
因此,该方法检查保存预设的文件是否存在-如果不存在,则应设置一个空预设并将其保存到新创建的文件中,否则应从现有文件加载预设

序列化过程工作正常,但是,由于我序列化到
,因此反序列化存在问题:

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()
,因此反序列化程序在一个永无止境的循环中调用自己,导致stackoverflow错误

因此,最简单的解决方案应该是使用另一个带参数的构造函数,在这里我调用
InitializePresetsFromFile()
,对吗?这里的问题是ViewModel类直接在相应视图的xaml中实例化:

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

第二个答案指出,约定是,从XAML调用的构造函数应该是无参数的,我想坚持这一点

问题:


问题只是如何根据最佳实践解决这个问题。由于这是我第一次尝试序列化和反序列化,我担心我在这里走错了一点。我的感觉是只有数据模型类应该被序列化。我的ViewModel包含两个此类的ObservableCollection,但是我希望序列化完整的集合以及ViewModel中的其他属性,例如所选索引

你确实已经到了必须决定如何继续下去的地步。你现在所做的是行不通的。在这种情况下,XML序列化程序和XAML都使用默认构造函数。你不能让它有两个目的

我的建议是创建一个类,该类从用于反序列化XML文件的视图模型中镜像属性。这个类只需要属性,不需要更多


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

首先,不应在类的构造函数中调用
InitializePresetsFromFile
方法。构造器必须尽可能快,并且不应造成副作用。在构造函数中读取文件是一种糟糕的做法:如果不访问文件系统,就不能创建类的实例。这意味着您的代码不可测试,容易出错(例如,您是否考虑过突发
UnauthorizedAccessException
s?),而且速度很慢

相反,创建一个对文件中的数据进行反序列化的公共方法。这将打破你无休止的递归

如何调用该方法

  • 您真的需要资源字典中的
    linearaxiscolorpestsviewmodel
    实例吗?如果没有,只需将反序列化实例分配给视图的
    DataContext
    属性即可
  • 如果确实需要,请在视图模型中创建一个
    ICommand
    ,例如
    InitializeCommand
    ,它使用上述方法从文件初始化内部状态;在应用程序启动/查看显示等时执行该命令。您可以使用例如
    InvokeCommandAction
    作为加载的
    事件

嗯,我害怕这个答案……我将研究一下您建议使用的定位器类,看看是否可以在我的案例中实现它。谢谢将使用这种方法找出谁在调用构造函数,并且只调用
InitializePresetsFromFile()良好实践?我仍然需要测试它,但我想它应该可以工作。我不建议这样做。让下一位看到该代码的同事知道它做了什么,不要做这些模糊的事情……这些都是有效的观点。我可能会尝试按照Patrick Hofman的建议将序列化所需的所有数据放在自己的类中,并按照您的建议从
loaded
事件开始反序列化过程。