反序列化为 List(Of T) 时传递构造函数参数

Pass constructor arguments when deserializing into a List(Of T)

我需要通过 JSON.Net 序列化和反序列化一个 List(of T),其中 T 是一个包含无法序列化的引用的对象。这是一个简化版本:

Class MyObject

    Private ReadOnly _Parent As Word.Document

    Property Foo As String
    Property Bar As String

    Sub New(Parent As Word.Document, Foo As String, Bar As String)
        Me.New(Parent)
        Me.Foo = Foo
        Me.Bar = Bar
    End Sub

    Sub New(Parent As Word.Document)
        _Parent = Parent
    End Sub

    <JsonConstructor>
    Private Sub New()
    End Sub

    Function GetFile() As System.IO.FileInfo
        Return New FileInfo(_Parent.FullName)
    End Function

End Class

为了这个故事,我将 JSON 字符串(序列化列表)存储在一个 Word 文档变量中。当我打开文档时,我获取字符串,反序列化它,然后我希望能够设置 _Parent 字段来引用同一个文档。 困难不在于知道 _Parent 应该引用什么,而在于设置引用。请注意,我想保留它 Private,但如有必要,它可以是 read/write。

有没有办法告诉 JSON.Net 使用 New(Parent As Word.Document) 构造函数,并通过 JsonConvert.DeserializeObject(Of T) 传递此 Parent 参数? 或者至少告诉 JSON.Net 我想 运行 一个特定的 Sub before/after 反序列化?

一个简单的绕过方法是使用下面的构造函数,但我不喜欢它,因为如果同时打开多个文档,它可能会变得混乱。

<JsonConstructor>
Private Sub New()
    _Parent = ThisWordApp.ActiveDocument
End Sub

我可以接受 C# 中的响应。

您可以采用 this answer to Pass additional data to JsonConverter and create a CustomCreationConverter(Of MyObject) 中的第二种方法,即使用传递给转换器本身的 Word.Document 分配 MyObject 的实例。

首先,定义如下转换器:

Class MyObjectConverter
    Inherits CustomCreationConverter(Of MyObject)

    Private ReadOnly _Parent As Word.Document           

    Sub New(Parent As Word.Document)
        If Parent Is Nothing Then
            Throw New ArgumentNullException("Parent")
        End If
        _Parent = Parent
    End Sub

    Overrides Function Create(objectType as Type) As MyObject
        Return New MyObject(_Parent)
    End Function
End Class

那么就可以这样使用了:

Dim settings = New JsonSerializerSettings() With { .Converters = { new MyObjectConverter(document) } }
Dim list = JsonConvert.DeserializeObject(Of List(Of MyObject))(jsonString, settings)

备注:

  • 此解决方案的额外优势是您不再需要 MyObject<JsonConstructor> Private Sub New() 构造函数,并且可以完全删除它。

  • 此转换器永远不会在编译时使用 JsonConverterAttribute 应用,它应该只在给定已知 Word.Document 的情况下在运行时构造(document 变量上面的代码示例)。

演示 fiddle here.