反序列化为 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.
我需要通过 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.