【问题标题】:Pass constructor arguments when deserializing into a List(Of T)反序列化为 List(Of T) 时传递构造函数参数
【发布时间】:2019-05-27 03:17:49
【问题描述】:

我需要通过 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,但是如果需要它可以是读/写的。

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

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

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

我对 C# 中的响应很好。

【问题讨论】:

  • Word.Document 是在文档打开时由 Word COM 模型创建的引用。不确定您所说的“修改”是什么意思,但对于给定的文档,如果我关闭并重新打开它,Word.Document 引用会有所不同。是的,Collection(Of T) 很好。
  • 这个想法是我有一个我正在处理的文档,我做一些事情来创建一些 MyObjects。我保存文档并关闭它(这些对象的列表/集合被序列化到文档中)。改天我打开文档,MyObjects 的列表/集合可用。
  • 在您提到的文章之后,看起来我可以使用&lt;OnDeserialized&gt; 属性,但我仍然无法将Word.Document 对象作为Sub 的参数传递给运行OnDeserializednewtonsoft.com/json/help/html/SerializationCallbacks.htm
  • Word.Document 无法修改。 docs.microsoft.com/en-us/dotnet/api/…
  • 你可以考虑Pass additional data to JsonConverter的方法。

标签: .net vb.net json.net office-interop


【解决方案1】:

您可以采用从this answerPass additional data to JsonConverter 的第二种方法,并使用传递给转换器本身的Word.Document 创建一个分配MyObject 实例的CustomCreationConverter(Of 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&lt;JsonConstructor&gt; Private Sub New() 构造函数,并且可以完全删除它。

  • 1234563

演示小提琴here.

【讨论】:

猜你喜欢
  • 2016-03-24
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多