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

Newtonsoft JSON自定义集合反序列化报错:无法创建并填充列表类型的解决咨询

解决Newtonsoft.Json反序列化自定义集合时的"Cannot create and populate list type"异常

这个问题的核心原因是Newtonsoft.Json在反序列化集合类型时,依赖于ICollection<T>接口来识别可填充的集合结构。你的ObservableCollectionAdvanced<T>虽然包装了ObservableCollection<T>,但只实现了IEnumerable<T>,Json.NET无法找到正确的方式来创建并填充这个自定义集合实例,所以抛出了异常。而ObservableCollection<T>本身是实现了ICollection<T>的,所以它能正常被反序列化。

解决方案:让自定义集合实现ICollection<T>接口

只需要给你的ObservableCollectionAdvanced<T>添加ICollection<T>的实现,把对应的成员委托给内部的_collection实例即可。这样Json.NET就能识别它为标准的可填充集合,同时也让你的自定义集合符合.NET的集合设计规范。

修改后的完整类代码如下:

Public Class ObservableCollectionAdvanced(Of T As INotifyPropertyChanged)
    Implements IEnumerable(Of T)
    Implements INotifyPropertyChanged
    Implements INotifyCollectionChanged
    Implements INotifyCollectionItemPropertyChanged
    Implements ICollection(Of T) ' 新增ICollection<T>接口实现

    Private ReadOnly _collection As New ObservableCollection(Of T)

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    Public Event CollectionChanged As NotifyCollectionChangedEventHandler Implements INotifyCollectionChanged.CollectionChanged
    Public Event CollectionItemPropertyChanged As PropertyChangedEventHandler Implements INotifyCollectionItemPropertyChanged.CollectionItemPropertyChanged

    Public Sub New()
        AddHandler _collection.CollectionChanged, Sub(sender As Object, e As NotifyCollectionChangedEventArgs)
                                                     RaiseEvent CollectionChanged(Me, e)
                                                 End Sub
    End Sub

    Default Public ReadOnly Property Item(Index As Integer) As T
        Get
            If Index >= 0 AndAlso Index < _collection.Count Then
                Return _collection(Index)
            Else
                Return Nothing
            End If
        End Get
    End Property

    Public Sub Add(Item As T) Implements ICollection(Of T).Add
        If Item IsNot Nothing Then
            Me.AddHandlerToItem(Item)
            _collection.Add(Item)
        End If
    End Sub

    Private Sub AddHandlerToItem(Item As T)
        AddHandler Item.PropertyChanged, AddressOf Item_PropertyChanged
    End Sub

    Private Sub Item_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
        RaiseEvent CollectionItemPropertyChanged(sender, e)
    End Sub

    Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
        Return _collection.GetEnumerator()
    End Function

    Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
        Return Me.GetEnumerator()
    End Function

    ' --- ICollection<T>接口成员实现 ---
    Public ReadOnly Property Count As Integer Implements ICollection(Of T).Count
        Get
            Return _collection.Count
        End Get
    End Property

    Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of T).IsReadOnly
        Get
            Return False ' ObservableCollection本身不是只读集合
        End Get
    End Property

    Public Sub Clear() Implements ICollection(Of T).Clear
        ' 清理每个元素的PropertyChanged事件处理器,避免内存泄漏
        For Each item In _collection
            RemoveHandler item.PropertyChanged, AddressOf Item_PropertyChanged
        Next
        _collection.Clear()
    End Sub

    Public Function Contains(Item As T) As Boolean Implements ICollection(Of T).Contains
        Return _collection.Contains(Item)
    End Function

    Public Sub CopyTo(array() As T, arrayIndex As Integer) Implements ICollection(Of T).CopyTo
        _collection.CopyTo(array, arrayIndex)
    End Sub

    Public Function Remove(Item As T) As Boolean Implements ICollection(Of T).Remove
        If _collection.Remove(Item) Then
            ' 移除元素时记得解绑事件处理器
            RemoveHandler Item.PropertyChanged, AddressOf Item_PropertyChanged
            Return True
        End If
        Return False
    End Function
End Class

为什么这样能解决问题?

当Json.NET处理集合反序列化时,会执行以下逻辑:

  1. 检查目标类型是否实现了ICollection<T>。
  2. 如果实现了,通过无参构造函数创建集合实例(你的类已经有了无参构造)。
  3. 遍历JSON中的每个元素,调用集合的Add方法将元素添加进去。

实现ICollection<T>不仅解决了Json.NET的反序列化问题,还让你的自定义集合拥有了标准.NET集合的所有核心行为,在其他场景下使用也会更顺畅。

额外注意事项

  • 你已经使用了TypeNameHandling.All,这确保了Json.NET能正确反序列化IDevice的具体实现类(比如TorsionArmDevice),这部分不需要调整。
  • 在Clear和Remove方法中添加了解绑事件处理器的逻辑,能避免内存泄漏,这是自定义集合绑定元素事件时的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:07:50