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

VB.NET自定义类型字典转对象:解决设计器类型转换错误

问题解决与对象转换器实现

一、先解决类型不匹配错误

你遇到的这个错误,本质是CLR将看似相同的类型判定为不同类型——通常是因为设计器加载时,Dictionary(Of Integer, RegistryDataItem)或RegistryDataItem被不同的程序集加载上下文加载(比如设计器引用了程序集副本,和运行时的程序集实例不统一)。解决这个问题最可靠的方式是替换默认Dictionary为自定义强类型集合,而非直接使用泛型字典作为设计属性类型:

1. 自定义强类型字典集合

创建一个继承自KeyedCollection(Of Integer, RegistryDataItem)的类,既保留字典的键值对特性,又能被设计器更好地识别:

<Serializable>
Public Class RegistryDataDictionary
    Inherits KeyedCollection(Of Integer, RegistryDataItem)

    ' 重写GetKeyForItem,指定RegistryDataItem的某个属性作为键(替换为你实际的键属性,比如item.Id)
    Protected Overrides Function GetKeyForItem(item As RegistryDataItem) As Integer
        Return item.Id
    End Function

    ' 可选:添加便捷的键值对添加方法
    Public Sub Add(id As Integer, item As RegistryDataItem)
        MyBase.Add(item)
    End Sub
End Class

2. 修改原属性定义

把原来的Dictionary类型替换成这个自定义集合:

Protected RegistryDatasValue As New RegistryDataDictionary()
<ProviderType(ProvideTypes.RegistryData)>
<Browsable(True), RefreshProperties(RefreshProperties.All)>
<Editor(GetType(StringTableCollectionEditor), GetType(Drawing.Design.UITypeEditor))>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
Public Property RegistryDatas() As RegistryDataDictionary
    Get
        Return RegistryDatasValue
    End Get
    Set(ByVal value As RegistryDataDictionary)
        RegistryDatasValue = value
    End Set
End Property

二、为自定义字典实现对象转换器(TypeConverter)

如果需要为自定义集合添加设计器转换支持(序列化、反序列化、类型转换),可以实现TypeConverter类:

1. 创建自定义TypeConverter类

Imports System.ComponentModel
Imports System.Globalization

Public Class RegistryDataDictionaryConverter
    Inherits TypeConverter

    ' 允许从字符串转换为目标类型
    Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
        If sourceType = GetType(String) Then
            Return True
        End If
        Return MyBase.CanConvertFrom(context, sourceType)
    End Function

    ' 实现从字符串到字典的转换(根据实际序列化格式调整解析逻辑)
    Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
        If TypeOf value Is String Then
            Dim dict As New RegistryDataDictionary()
            ' 假设序列化格式为"键1:项内容1;键2:项内容2",可根据实际需求修改
            Dim parts As String() = DirectCast(value, String).Split(";"c)
            For Each part In parts
                If Not String.IsNullOrEmpty(part) Then
                    Dim keyValue As String() = part.Split(":"c)
                    If keyValue.Length = 2 Then
                        Dim id As Integer = Integer.Parse(keyValue(0))
                        ' 这里假设RegistryDataItem有FromString方法,或自行实例化对象
                        Dim item As RegistryDataItem = RegistryDataItem.FromString(keyValue(1))
                        dict.Add(id, item)
                    End If
                End If
            Next
            Return dict
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function

    ' 允许转换为字符串(用于设计器属性栏显示)
    Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean
        If destinationType = GetType(String) Then
            Return True
        End If
        Return MyBase.CanConvertTo(context, destinationType)
    End Function

    ' 实现从字典到字符串的转换
    Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
        If destinationType = GetType(String) AndAlso TypeOf value Is RegistryDataDictionary Then
            Dim dict As RegistryDataDictionary = DirectCast(value, RegistryDataDictionary)
            Dim parts As New List(Of String)()
            For Each item In dict
                parts.Add($"{item.Id}:{item.ToString()}") ' 用Item的ToString或自定义属性生成显示字符串
            Next
            Return String.Join(";", parts)
        End If
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function
End Class

2. 为自定义字典绑定转换器

在RegistryDataDictionary类上添加特性,关联刚才的转换器:

<Serializable>
<TypeConverter(GetType(RegistryDataDictionaryConverter))>
Public Class RegistryDataDictionary
    Inherits KeyedCollection(Of Integer, RegistryDataItem)
    ' ... 原有代码 ...
End Class

额外注意事项

  • 确保RegistryDataItem类的<Serializable>特性正确,若有自定义序列化逻辑,可实现ISerializable接口。
  • 若使用自定义的StringTableCollectionEditor,需确保它支持新的RegistryDataDictionary类型,必要时调整编辑器代码。
  • 强命名你的程序集,避免设计器加载时出现程序集版本冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:31:04