c#加载序列化文件失败 - 类属性i:键入

时间:2016-03-10 10:58:47

标签: c# xml serialization win-universal-app datacontractserializer

我正在尝试编写家庭自动化软件。目前我有以下课程:

- 首页
-Room
-Device
-WindowShutter(继承自设备)
-Sensor(从设备继承)

目前,包含Rooms(包含设备)的Home对象以XML格式保存。

public static async void SaveHome(Home MyHome)
        {
            MemoryStream _MemoryStream = new MemoryStream();
            DataContractSerializer Serializer = new DataContractSerializer(typeof(Home));
            Serializer.WriteObject(_MemoryStream, MyHome);

            StorageFile _File = await ApplicationData.Current.LocalFolder.CreateFileAsync("Home2.bin", CreationCollisionOption.ReplaceExisting);

            using (Stream fileStream = await _File.OpenStreamForWriteAsync())
            {
                _MemoryStream.Seek(0, SeekOrigin.Begin);
                await _MemoryStream.CopyToAsync(fileStream);
                await fileStream.FlushAsync();
                fileStream.Dispose();
            }
        }

由于设备类型不同,保存的文件如下所示:

<Home xmlns="http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>My Home</Name>
<Rooms>
<Room><Color/><Devices><Device><I2C_Slave_Address>64</I2C_Slave_Address><Id>0</Id><ImagePath i:nil="true"/><Name>My Device</Name><Pin>D0</Pin></Device>
<Device i:type="WindowShutter"><I2C_Slave_Address>64</I2C_Slave_Address><Id>1</Id><ImagePath i:nil="true"/><Name>My Window Shutter</Name><Pin>D0</Pin><SecondaryPin>D1</SecondaryPin></Device>
<Device i:type="Sensor"><I2C_Slave_Address>64</I2C_Slave_Address><Id>2</Id><ImagePath i:nil="true"/><Name>My Sensor</Name><Pin>A2</Pin></Device></Devices><I2C_SlaveAdress>64</I2C_SlaveAdress>
<Name>Room</Name></Room></Rooms></Home>

问题是,只要我第二次启动程序并加载Home2.bin文件,我就会收到以下错误:

Aggregate Exception

这是加载文件的方法:

public static async Task<Home> LoadHome()
        {
            StorageFolder _Folder = ApplicationData.Current.LocalFolder;
            StorageFile _File;

            try
            {
                _File = await _Folder.GetFileAsync("Home2.bin");

                Stream stream = await _File.OpenStreamForReadAsync();

                DataContractSerializer Serializer = new DataContractSerializer(typeof(Home));

                return (Home)Serializer.ReadObject(stream);
            }
            catch (FileNotFoundException)
            {
                return new Home();
            }
        }

我发现,当我从Home2.bin文件中的设备元素中删除i:type属性时,将加载该文件。但是当我删除它时,设备会丢失它们的类型,并且不会按预期工作。

你知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

您看到该异常的原因是DataContractSerializer要求在序列化期间遇到的所有类型都可以通过反射静态发现 。如果遇到意外类型 - 包括多态类型的子类 - 它会抛出异常。

对于多态类型,您可以使用[KnownTypeAttribute]通知序列化程序预期的子类型。完成后,"{http://www.w3.org/2001/XMLSchema-instance}type"属性将指示已序列化的实际合同的名称。

因此,您的课程应该类似于:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")]
[KnownType(typeof(WindowShutter))]
[KnownType(typeof(Sensor))]
public class Device
{
    [DataMember]
    public int I2C_Slave_Address { get; set; }

    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string ImagePath { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Pin { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")]
public class WindowShutter : Device
{
    [DataMember]
    public string SecondaryPin { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")]
public class Sensor : Device
{
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")]
public class Home
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public List<Room> Rooms { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")]
public class Room
{
    [DataMember]
    public string Color { get; set; }

    [DataMember]
    public List<Device> Devices { get; set; }

    [DataMember]
    public int I2C_SlaveAdress { get; set; }

    [DataMember]
    public string Name { get; set; }
}

有关详情,请参阅Data Contract Known TypesKnown Types