You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Newtonsoft.Json反序列化时如何传入ExchangeClass参数初始化对象?

问题

我通常通过以下方式创建BasicSimpleOrder对象:

Public Shared Function createBasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeObject As ExchangesClass, isSellingInsteadOfBuying As Boolean, customIdentifier As String) As BasicSimpleOrder
    Dim exchangeString = exchangeObject.ExchangeStringName
    Dim a = New BasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered, priceInBasecoin, Base, Quote, exchangeString, isSellingInsteadOfBuying, customIdentifier)
    a.initializeComplexObjects(exchangeObject)
    Return a
End Function

其中exchangeObject As ExchangesClass是BasicSimpleOrder中唯一的非基元类型成员,我会在设置基元只读属性后调用initializeComplexObjects方法完成复杂对象初始化:

Public Sub initializeComplexObjects(exchangeObject As ExchangesClass)
    _exchangeObject = exchangeObject
    If exchangeObject Is Nothing Then Exit Sub
    Dim mark = CoinClass.MarketBaseQuoted(exchangeObject.ExchangeStringName, Base, Quote)
    If mark Is Nothing Then Exit Sub
    setMarket(mark)
End Sub

现在需要反序列化包含BasicSimpleOrder派生类的futureStateForGrid对象,使用代码:

gridOrderOldState = Newtonsoft.Json.JsonConvert.DeserializeObject(Of futureStateForGrid)(settingsFromBefore)

BasicSimpleOrder的构造函数如下:

Protected Sub New(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeString As String, isSellingInsteadOfBuying As Boolean, customIdentifier As String)
    _ammountOfQuoteCurrencyBeingOrdered = ammountOfQuoteCurrencyBeingOrdered
    _Base = Base
    _Quote = Quote
    _priceInBasecoin = priceInBasecoin
    _exchangeString = exchangeString
    _isSellingInsteadOfBuying = isSellingInsteadOfBuying
    _customIdentifier = customIdentifier
End Sub

核心问题:反序列化时无法自动调用initializeComplexObjects(exchangeObject As ExchangesClass)——构造函数不能接收ExchangesClass类型参数(因为该类型未被序列化,Json.NET无法生成对应实例),但反序列化完成后需要传入exchangeObject来完成BasicSimpleOrder的复杂成员初始化。

解决方案

方案1:反序列化后手动遍历调用初始化方法

这是最直接的方案,反序列化完成后,遍历futureStateForGrid中所有BasicSimpleOrder(或其派生类)对象,逐个调用initializeComplexObjects方法,传入对应的exchangeObject。

假设futureStateForGrid包含一个Orders属性(存储所有订单对象),代码示例:

' 先完成反序列化
gridOrderOldState = Newtonsoft.Json.JsonConvert.DeserializeObject(Of futureStateForGrid)(settingsFromBefore)

' 遍历所有订单,调用初始化方法
For Each order In gridOrderOldState.Orders
    If TypeOf order Is BasicSimpleOrder Then
        DirectCast(order, BasicSimpleOrder).initializeComplexObjects(yourExchangeObject)
    End If
Next

如果订单嵌套在更复杂的结构里,只需要调整遍历逻辑,找到所有BasicSimpleOrder派生类实例即可。

方案2:利用Json.NET的OnDeserialized特性延迟初始化

如果exchangeObject可以通过已序列化的exchangeString属性获取(比如全局维护一个ExchangesClass的字典,用exchangeString做键),可以在BasicSimpleOrder中添加OnDeserialized标记的方法,在反序列化完成后自动触发初始化:

Imports Newtonsoft.Json

Public Class BasicSimpleOrder
    ' 原有代码...

    <OnDeserialized()>
    Private Sub OnDeserializedMethod(context As StreamingContext)
        ' 假设你有全局的Exchange管理类,能通过exchangeString获取对应的ExchangesClass实例
        Dim exchangeObject = ExchangeManager.GetExchangeByString(_exchangeString)
        initializeComplexObjects(exchangeObject)
    End Sub
End Class

这种方案无需手动遍历,反序列化后会自动执行初始化逻辑,但前提是你能通过exchangeString拿到对应的ExchangesClass实例。

方案3:调整类设计为懒加载模式

把_exchangeObject和相关的Market对象改为懒加载,在第一次使用时再初始化,这样反序列化后不用立刻调用初始化方法,用到的时候自动完成:

Public Class BasicSimpleOrder
    Private _exchangeObject As ExchangesClass
    Private _lazyExchange As Lazy(Of ExchangesClass)
    Private _lazyMarket As Lazy(Of MarketClass) ' 假设MarketClass是setMarket的参数类型

    ' 原有构造函数不变,添加懒加载初始化
    Protected Sub New(...)
        ' 原有代码...
        _lazyExchange = New Lazy(Of ExchangesClass)(Function() ExchangeManager.GetExchangeByString(_exchangeString))
        _lazyMarket = New Lazy(Of MarketClass)(Function() 
            Dim exch = _lazyExchange.Value
            If exch Is Nothing Then Return Nothing
            Return CoinClass.MarketBaseQuoted(exch.ExchangeStringName, Base, Quote)
        End Function)
    End Sub

    ' 修改原有属性,用懒加载的实例
    Public ReadOnly Property ExchangeObject As ExchangesClass
        Get
            Return _lazyExchange.Value
        End Get
    End Property

    Public ReadOnly Property Market As MarketClass
        Get
            Return _lazyMarket.Value
        End Get
    End Property

    ' 可以保留原有的initializeComplexObjects方法,作为手动触发的选项
    Public Sub initializeComplexObjects(exchangeObject As ExchangesClass)
        If _exchangeObject Is Nothing Then
            _exchangeObject = exchangeObject
            ' 手动初始化Market
            Dim mark = CoinClass.MarketBaseQuoted(exchangeObject.ExchangeStringName, Base, Quote)
            If mark IsNot Nothing Then
                setMarket(mark)
            End If
        End If
    End Sub
End Class

这种方案彻底解决了反序列化后的初始化问题,对象在第一次被使用时才会加载依赖的复杂类型,无需额外手动操作。

内容的提问来源于stack exchange,提问作者user4951

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:00:57