扩展 Newtonsoft.Json.Linq.JObject Class

Extend Newtonsoft.Json.Linq.JObject Class

我想扩展 Newtonsoft.Json.Linq.JObject Class 以便快速访问(以属性的形式)从 JObject 的内容中即时生成的某些表达式。让我们调用扩展 class JRecord.

我还需要 JObject 个实例可以轻松地与扩展类型 JRecord 相互转换。问题是:我如何获取一个 JObject 实例并将其转换为我的扩展类型(它也继承自 JObject),以某种方式保留其所有内容但获得 "dressed"从 JObject 缩小到 JRecord 时的额外属性以及从 JRecord 扩大到 JObject?

时这些属性的 "striped"

下面是我的第一个草稿,我省略了大部分属性,因为它的字符串构建很复杂并且与问题无关,这会引发两个自定义 CType() 运算符,其中 .NET 告诉我

  1. Conversion operators cannot convert from a type to its base type

  2. Conversion operators cannot convert from a base type

那么,我该怎么办?我应该创建一个全新的实例并创建与我要投射的对象具有相同内容的子对象吗?

Public Class JRecord
    Inherits JObject

    Public Sub New()
        MyClass.New
    End Sub

    Public ReadOnly Property Id As Integer
        Get
            Return MyBase.Value(Of Integer)("id")
        End Get
    End Property

    Public ReadOnly Property NomeSigla As String
        Get
            Return String.Format(
                "{0} ({1})", 
                MyBase.Value(Of String)("nome"), 
                MyBase.Value(Of String)("sigla"))
        End Get
    End Property

    Public Overloads Shared Narrowing Operator CType(json_object As JObject) As JRecord
        Return DirectCast(json_object, JRecord)
    End Operator

    Public Overloads Shared Widening Operator CType(json_record As JRecord) As JObject
        Return json_record
    End Operator

End Class

在这种情况下我不会使用继承和转换运算符。相反,我会在这里使用组合。换句话说,使 JRecord class 包装原始 JObject 并根据需要委托给它。要从 JObject 转换为 JRecord,请使 JRecord 的构造函数接受 JObject。要走另一条路,只需在 JRecord 上制作 JObject 属性 并直接将其 return 放在内部 JObject 中。

Public Class JRecord

    Private innerJObject As JObject

    Public Sub New(jObject As JObject)
        innerJObject = jObject
    End Sub

    Public ReadOnly Property JObject As JObject
        Get
            Return innerJObject
        End Get
    End Property

    Public ReadOnly Property Id As Integer
        Get
            Return innerJObject.Value(Of Integer)("id")
        End Get
    End Property

    Public ReadOnly Property NomeSigla As String
        Get
            Return String.Format(
                "{0} ({1})",
                innerJObject.Value(Of String)("nome"),
                innerJObject.Value(Of String)("sigla"))
        End Get
    End Property

End Class

那么你可以这样做:

Dim jr as JRecord = new JRecord(JObject.Parse(jsonString))
Dim id as Integer = jr.Id
Dim ns as String = jr.NomeSigla
Dim jo as JObject = jr.JObject
...

如果你绝对必须使用继承,因为你想将 JRecord 直接传递到应用程序中只需要 JObject 的其他地方,你可以这样做:

Public Class JRecord
    Inherits JObject

    Public Sub New(jObject As JObject)
        MyBase.New(jObject)
    End Sub

    Public ReadOnly Property JObject As JObject
        Get
            Return Me
        End Get
    End Property

    Public ReadOnly Property Id As Integer
        Get
            Return Value(Of Integer)("id")
        End Get
    End Property

    Public ReadOnly Property NomeSigla As String
        Get
            Return String.Format(
                "{0} ({1})",
                Value(Of String)("nome"),
                Value(Of String)("sigla"))
        End Get
    End Property

End Class

这几乎是一回事,只是现在 JRecord JObject,因此您可以自由传递它。权衡是现在它必须在 JRecord 首次构造时复制所有属性。我们利用 JObject 的内置复制构造函数来执行此操作。