【发布时间】:2019-07-30 15:22:12
【问题描述】:
对于我的一个对象,我需要做一些向后/向前兼容技巧,以便在不同版本共存并共享相同配置文件时每个人都感到高兴。
我尝试的最后一个技巧是创建一个 bridge 集合,该集合使用 IEnumerable(Of String) 将旧格式映射到新格式。我的问题是我无法让XmlSerializer 识别我的自定义集合。我查看了生成代码的序列化程序代码,一切似乎都很好。不管我做什么,只要我使用我的自定义集合ListeCategories 最终会在Unsupported 中。如果我使用基本的List(Of String),它可以工作,但我错过了逻辑。我错过了什么?
我还尝试了一个非通用自定义集合(在第二个代码 sn-p 中注释),但没有更多成功。
这里是主对象和自定义集合的代码。
请注意,XmlSerializer(根据MS Docs)要求的自定义可枚举实现和附加Add 方法。
XmlSerializer 对实现 IEnumerable 或 ICollection 的类进行特殊处理。实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。 Add 方法的参数必须与从 GetEnumerator 返回的值的 Current 属性返回的类型相同,或者该类型的基数之一。除了 IEnumerable 之外,实现 ICollection(如 CollectionBase)的类必须具有一个采用整数的公共 Item 索引属性(C# 中的索引器),并且它必须具有一个整数类型的公共 Count 属性。 Add 方法的参数必须与从 Item 属性返回的类型相同,或者是该类型的基数之一。对于实现 ICollection 的类,要序列化的值是从索引的 Item 属性中检索的,而不是通过调用 GetEnumerator。
Public Class OptionsSerializable
Public Sub New()
End Sub
<XmlAnyElement>
Public Property Unsupported As List(Of XmlElement)
<System.Xml.Serialization.XmlElement(ElementName:="ListeCategoriesExt")>
Public ReadOnly Property Categories As List(Of CategoryInfo)
Public ReadOnly Property ListeCategories As IEnumerable(Of String) = New EnumerableBridge(Of String, CategoryInfo)(_categories, Function(s) New CategoryInfo(s), Function(c) c.SearchTerm)
Public Property ServeurExchangeUrl As String
Public Property VersionExchange As String
Public Property AdresseBoitePartager As New List(Of String)
Public Property GroupingMasks As New List(Of String)
Public Property TFSLinks As New XmlSerializableDictionary(Of String, String)
Public Property EstAlertageActif As Boolean
Public Property Laps As Integer
Public Property NbErreursMaximum As Integer
Public Property DerniereVerification As Date
Public Property ListeEnvoi As String
Public Property DernierEnvoi As Date
Public Property LogonDernierEnvoi As String
Public Property IntervalEnvoiMinimum As Integer
End Class
'Public Class SpecificCollectionBridge
' Inherits CollectionBridge(Of String, CategoryInfo)
' Public Sub New(refCollection As IEnumerable(Of CategoryInfo))
' MyBase.New(refCollection, Function(s) New CategoryInfo(s), Function(c) c.SearchTerm)
' End Sub
'End Class
<Serializable>
Public Class EnumerableBridge(Of TSource, TTarget)
Implements IEnumerable(Of TSource)
Private _refCollection As IList(Of TTarget)
Private _converterTo As Func(Of TSource, TTarget)
Private _converterFrom As Func(Of TTarget, TSource)
Public Sub New()
End Sub
Public Sub New(refCollection As IList(Of TTarget), converterTo As Func(Of TSource, TTarget), converterFrom As Func(Of TTarget, TSource))
_refCollection = refCollection
_converterTo = converterTo
_converterFrom = converterFrom
End Sub
Public Sub Add(item As TSource) 'Implements ICollection(Of TSource).Add
_refCollection.Add(_converterTo(item))
End Sub
Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
Public Function IEnumerableOfT_GetEnumerator() As IEnumerator(Of TSource) Implements IEnumerable(Of TSource).GetEnumerator
Return _refCollection.Select(_converterFrom).GetEnumerator()
End Function
End Class
【问题讨论】:
标签: .net vb.net xmlserializer