灵活序列化的任何想法

Posted

技术标签:

【中文标题】灵活序列化的任何想法【英文标题】:Any ideas for flexible serialization 【发布时间】:2012-07-05 21:20:30 【问题描述】:

我有一些序列化输出的对象。对象的某些属性计算起来很繁重,需要一些时间来计算。我正在考虑的是如何指定用户想要获取的属性集并仅序列化该集而不是全部序列化。

我已经做了一些研究,很清楚如何仅序列化标有 [Serializable] 属性的对象的所需属性,但在我的情况下,标有 [DataContract] 的对象我仍然有一些问题。

现在的另一个问题是指定应该序列化的属性集。理想情况下,最好有类似 XQuery 的东西来指定究竟应该序列化什么。

所以,现在问题多于答案...欢迎任何想法/想法//建议!

【问题讨论】:

【参考方案1】:

以下示例创建了一个简单的建筑,它有 3 层,每层有 4 个房间。这不是一个过于复杂的对象图,但我认为它应该能够理解这个想法。这个想法是你可以实现System.Runtime.Serialization.ISerializable来控制序列化过程。

在这个例子中,我只为 Floors 类型实现了System.Runtime.Serialization.ISerializable。在楼层类型中,我控制房间列表的序列化和反序列化方式。

由于不了解您的类型的具体细节,特别是计算量大的属性,我无法具体与他们交谈;但是,我认为通过使用实现System.Runtime.Serialization.ISerializable 提供的技术并控制序列化过程,您将能够实现您正在寻找的结果。

请记住,您可以将任何内容添加到序列化流中,并且不需要在您的类中添加所有内容;但是,您至少希望在反序列化构造函数运行后使您的类“正确”。放入序列化流中的内容取决于您。

但是请注意,这仅适用于 二进制序列化,不适用于 Xml 序列化

    Module Module1

    Sub Main()
        Dim floor1 As New Floor()
        floor1.Rooms.Add(New Rooms(101))
        floor1.Rooms.Add(New Rooms(102))
        floor1.Rooms.Add(New Rooms(103))
        floor1.Rooms.Add(New Rooms(104))

        Dim floor2 As New Floor()
        floor2.Rooms.Add(New Rooms(201))
        floor2.Rooms.Add(New Rooms(202))
        floor2.Rooms.Add(New Rooms(203))
        floor2.Rooms.Add(New Rooms(204))

        Dim floor3 As New Floor()
        floor3.Rooms.Add(New Rooms(301))
        floor3.Rooms.Add(New Rooms(302))
        floor3.Rooms.Add(New Rooms(303))
        floor3.Rooms.Add(New Rooms(304))

        Dim tower As New Building()
        tower.Floors.Add(floor1)
        tower.Floors.Add(floor2)
        tower.Floors.Add(floor3)

        Dim byteArray As Byte() = Serialized(tower)
        Dim backAgain As Building = DeSerialized(byteArray)
    End Sub

    Private Function Serialized(ByVal tower As Building) As Byte()
        Using ms As New System.IO.MemoryStream()
            Dim formatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            formatter.Serialize(ms, tower)
            Return ms.GetBuffer()
        End Using
    End Function

    Private Function DeSerialized(ByVal byteArray As Byte()) As Building
        Using ms As New System.IO.MemoryStream(byteArray)
            Dim formatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            ms.Position = 0
            Return DirectCast(formatter.Deserialize(ms), Building)
        End Using
    End Function
End Module

<Serializable()>
Public Class Building
    Public Sub New()
    End Sub

    Private _Floors As New List(Of Floor)
    Public ReadOnly Property Floors As List(Of Floor)
        Get
            Return _Floors
        End Get
    End Property
End Class

<Serializable()>
Public Class Floor
    Implements System.Runtime.Serialization.ISerializable

    Public Sub New()
    End Sub

    Public Sub New(ByVal info As Runtime.Serialization.SerializationInfo, ByVal context As Runtime.Serialization.StreamingContext)
        Dim counter As Integer = info.GetInt32("RoomCount")
        For index As Integer = 0 To counter - 1
            _Rooms.Add(DirectCast(info.GetValue(String.Format("Room0", index.ToString()), GetType(Rooms)), Rooms))
        Next
    End Sub

    Private _Rooms As New List(Of Rooms)
    Public ReadOnly Property Rooms As List(Of Rooms)
        Get
            Return _Rooms
        End Get
    End Property

    Public Sub GetObjectData(info As System.Runtime.Serialization.SerializationInfo, context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData
        info.AddValue("RoomCount", _Rooms.Count)
        For index As Integer = 0 To _Rooms.Count - 1
            info.AddValue(String.Format("Room0", index.ToString()), _Rooms(index))
        Next
    End Sub
End Class

<Serializable()>
Public Class Rooms
    Public Sub New()
    End Sub

    Public Sub New(ByVal roomNum As Integer)
        Me.New()
        _RoomNumber = roomNum
    End Sub

    Private _RoomNumber As Integer = 0
    Public Readonly Property RoomNumber As Integer
        Get
            Return _RoomNumber
        End Get
    End Property
End Class

【讨论】:

嗨兰迪,感谢您的回复!我知道提供 GetObjectData 的 ISerializable 接口和功能。但在我的情况下,我的对象用 [DataContract] 标记,在这种情况下我不能使用 ISerializable 接口。现在我正在查看 IDataContractSurrogate 接口及其提供的内容。无论如何,再次感谢您的回复!

以上是关于灵活序列化的任何想法的主要内容,如果未能解决你的问题,请参考以下文章

实体框架迁移错误 - 序列不包含任何元素

反序列化对象运行问题

在 Flutter 的 Ferry Graphql 中序列化标量 JSON 以实现灵活的查询

如何灵活运用EDIUS中序列嵌套功能

编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程

序列化数组中的mysql选择查询