2012-11-20 60 views
1

這是我的舊類圖(簡化版)。在DataContractSerializer中將已刪除的類型反序列化爲新類型(舊的基類)

public class Main 
    Public Property ListOfA As ClassACollection 
End Class 

Public Class ClassBase 
End Class 

Public Class ClassA 
    Inherits ClassBase 
End Class 

Public Class ClassACollection 
    Inherits System.Collections.ObjectModel.Collection(Of ClassA) 
End Class 

Public Class ClassB 
    Inherits ClassBase 
End Class 

Public Class ClassBCollection 
    Inherits System.Collections.ObjectModel.Collection(Of ClassB) 
End Class 

當我序列化的類MainDataContractSerializer我有這樣的XML:

<Main> 
    <ListOfA> 
    <ClassA> 
     ..... 
    </ClassA> 
    <ClassA> 
     ..... 
    </ClassA> 
    </ListOfA> 
</Main> 

最近我去除ClassAClassB原因,他們是相同的!我刪除了兼具收藏與此替換它們:

public class Main 
    Public Property ListOfA As ClassBaseCollection 
End Class 

Public Class ClassBaseCollection 
    Inherits System.Collections.ObjectModel.Collection(Of ClassBase) 
End Class 

但現在當我嘗試反序列化的XML,收集ListOfA被創建,但總是空空的!在反序列化過程中我沒有錯誤。

我試過使用DataContractResolver,但函數ResolveName從不要求ClassAClassB

Dim dc As New Runtime.Serialization.DataContractSerializer(GetType(Main), Nothing, Integer.MaxValue, False, True, Nothing, New MyResolver()) 

Private Class MyResolver 
    Inherits Runtime.Serialization.DataContractResolver 

    Public Overrides Function ResolveName(typeName As String, typeNamespace As String, declaredType As System.Type, knownTypeResolver As System.Runtime.Serialization.DataContractResolver) As System.Type 
     If typeName.Equals("ClassA") OrElse typeName.Equals("ClassB") Then 
     Return GetType(ClassBase) 
     Else 
     'Defer to the known type resolver 
     Return knownTypeResolver.ResolveName(typeName, typeNamespace, Nothing, Nothing) 
     End If 
    End Function 
End Class 

是做我想做什麼DataContractResolver好辦法嗎? 如果是,我是否需要別的方法才能使DataContractResolver工作?

感謝您的幫助!


更新: - 我試圖把它們是已知的數據類型在DataContractSerializer構造
我在我的項目做如下測試,加入背ClassAClassB
- 我嘗試了ClassBaseCollection`上的KnownTypeAttribute

在這2種情況下,ResolveName仍然不需要ClassAClassB

我試圖用派生的類從IDataContractSurrogate和轉換類型的功能GetDataContractType這個功能沒有要求ClassAClassB


更新#2: 最後,我沒有發現任何方式做我想要的。我需要查看文件版本,並在序列化之前用XML中的新標籤替換舊標籤。防爆。 :

data = data.Replace("<ClassA>", "<ClassBase>") 
... 

這不是我的第一個問題的答案,而是一種解決方法。

+0

[Data Contract Versioning](http://msdn.microsoft.com/zh-cn/library/ms731138.aspx)上的msdn頁面可能對您有用。 –

回答

1

但現在當我嘗試反序列化的XML,收集ListOfA是 創建,但總是空空的!在反序列化過程中我沒有錯誤。

msdn documentation on Data Contract Versioning中,您可以找到有關爲什麼ListOfA爲空的信息。您調整版本的反序列化引擎無法解釋ClassAClassB,因此會丟棄此數據。

我認爲你使用Data Contract Resolver進行正確的跟蹤。

數據合約解析器允許您動態配置已知類型 。 在序列化時需要已知的類型,或者對數據合同未預期的類型進行反序列化。

因爲你沒在DataContractSerializer constructor的已知數據類型參數指定ClassAClassBResolveName()不叫他們。有關已知數據類型的更多信息,請參閱check the msdn documentation。這意味着爲了正確反序列化這些舊類,您仍然需要包含它們以實現向後兼容。

+1

我明白爲什麼我的清單是空的。謝謝。是的,我正在反序列化。 ResolveName()調用其他類型,但不適用於ClassA或ClassB。我編輯我的帖子來澄清這一點。 – Kipotlov

+0

@Kipotlov恐怕你必須保留'ClassA'和'ClassB'聲明。看到我更新的答案。 –

+0

我試着在'DataContractSerializer'構造函數中將'ClassA'和'ClassB'作爲已知的數據類型,我嘗試了'ClassBaseCollection'上的'KnownTypeAttribute',並且仍然沒有爲'ClassA'和'ClassB'調用ResolveName' ... – Kipotlov

相關問題