2017-03-15 47 views
0

我想擴展Newtonsoft.Json.Linq.JObject類,以便快速訪問(以屬性的形式)某些從JObject內容中即時創建的表達式。讓我們打電話擴展類JRecord擴展Newtonsoft.Json.Linq.JObject類

我還需要JObject實例可以很容易地從擴展類型JRecord轉換而來。問題是:如何將JObject實例作爲我的擴展類型(它也繼承自JObject)以某種方式保留其所有內容,但在從JObject縮小爲JRecord和「當從JRecord擴大到JObject

下面是我的第一個從無到有,我省略了大部分的性能,因爲它的串建設是複雜的和不相關的問題,這引起了兩個自定義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 

回答

1

在這種情況下,我不會使用繼承和轉換運算符。相反,我會在這裏使用組合。換句話說,使JRecord類包裝原始JObject並根據需要委託給它。要從JObject轉換爲JRecord,請使JRecord的構造函數接受JObject。換一種方式,只需在JRecord上設置一個JObject財產,並讓它直接返回內部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 a JObject所以你可以自由傳遞它。權衡是現在它必須在JRecord第一次構建時複製所有屬性。我們利用JObject的內置拷貝構造函數來執行此操作。

+0

是的,當我繼續研究時,我發現這是在這裏工作的「適當」方式。但假設我有幾個操作返回'JObject'的類,現在將返回'JRecord'。我怎麼能讓這個新類型沿着應用程序的其餘部分無縫模仿'JObject',或者這是不可能的,而且我的目標太多了? (我知道我最好重新整理所有東西,而且我打算這樣做,但是我希望保持它在中間運行,即使比以前慢一點和重一點)。 – VBobCat

+1

對於需要JObject的地方,我只需更改調用者以傳遞'jRecord。JObject'而不是傳遞'jRecord'。但是如果有太多的地方需要改變,那麼你仍然可以做一個基於繼承的方法。我已經更新了我的答案以顯示如何。 –

+0

完美!非常感謝! – VBobCat