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

动态生成泛型类型失效:Get函数赋值抛出类型转换异常

解决动态创建BaSyx泛型Property时的委托类型转换异常

这个问题我之前也踩过坑,核心原因是:当你用Activator.CreateInstance创建泛型的Property(Of T)实例后,变量BasysEigenschaft的编译时类型是Object,直接给它的[Get]/[Set]属性赋值匿名函数时,VB.NET编译器会把匿名委托推断成非泛型的通用委托类型(比如VB$AnonymousDelegate_0(Of Object, Integer)),但实际上Property(Of T)的[Get]需要的是泛型的GetPropertyValueHandler(Of T)委托,两者类型不兼容,所以才会抛出InvalidCastException。

下面给你两个有效的解决方案:

方案一:通过反射匹配泛型委托类型

直接用反射获取泛型委托的类型,创建匹配的委托后再赋值给目标属性,步骤如下:

For Each Eigenschaft As PropertyInfo In Me.GetType().GetProperties()
    If Eigenschaft.CanRead = True Then
        Dim Eigenschaftstyp As Type = Eigenschaft.PropertyType
        ' 创建泛型Property(Of T)实例
        Dim GenerischerTypBasysProperty As Type = GetType(BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property(Of)).MakeGenericType(Eigenschaftstyp)
        Dim BasysEigenschaft = Activator.CreateInstance(GenerischerTypBasysProperty)
        
        ' 设置IdShort(也可以用反射,避免编译时类型问题)
        GenerischerTypBasysProperty.GetProperty("IdShort").SetValue(BasysEigenschaft, Eigenschaft.Name)
        
        ' 处理Get委托:创建匹配的泛型GetPropertyValueHandler(Of T)
        Dim getHandlerType As Type = GetType(BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes.GetPropertyValueHandler(Of)).MakeGenericType(Eigenschaftstyp)
        Dim getDelegate As [Delegate] = [Delegate].CreateDelegate(
            getHandlerType, 
            Me, 
            Function(prop) Eigenschaft.GetValue(Me) ' 这里的逻辑和你原来的一致
        )
        GenerischerTypBasysProperty.GetProperty("Get").SetValue(BasysEigenschaft, getDelegate)
        
        ' 处理Set委托(仅当属性可写时)
        If Eigenschaft.CanWrite Then
            Dim setHandlerType As Type = GetType(BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes.SetPropertyValueHandler(Of)).MakeGenericType(Eigenschaftstyp)
            Dim setDelegate As [Delegate] = [Delegate].CreateDelegate(
                setHandlerType, 
                Me, 
                Sub(prop, Wert) Eigenschaft.SetValue(Me, Wert)
            )
            GenerischerTypBasysProperty.GetProperty("Set").SetValue(BasysEigenschaft, setDelegate)
        End If
        
        MyBase.SubmodelElements.Add(BasysEigenschaft)
    End If
Next

方案二:用泛型方法封装创建逻辑

这种方式更简洁,利用泛型方法的编译时类型检查来避免委托转换问题,先定义一个泛型辅助方法,再通过反射调用它:

' 定义一个私有的泛型辅助方法,专门创建匹配类型的Property(Of T)
Private Function CreateBasysProperty(Of T)(propertyInfo As PropertyInfo, instance As Object) As BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property(Of T)
    Return New BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property(Of T)() With {
        .IdShort = propertyInfo.Name,
        .[Get] = Function(p) CType(propertyInfo.GetValue(instance), T),
        .[Set] = Sub(p, val) propertyInfo.SetValue(instance, val)
    }
End Function

' 在循环中调用这个泛型方法
For Each Eigenschaft As PropertyInfo In Me.GetType().GetProperties()
    If Eigenschaft.CanRead = True Then
        ' 获取泛型方法的实例化版本(指定当前属性的类型)
        Dim createMethod = GetType(YourClassName).GetMethod(
            "CreateBasysProperty", 
            BindingFlags.NonPublic Or BindingFlags.Instance
        ).MakeGenericMethod(Eigenschaft.PropertyType)
        
        ' 调用方法创建Property实例
        Dim BasysEigenschaft = createMethod.Invoke(Me, New Object() {Eigenschaft, Me})
        MyBase.SubmodelElements.Add(BasysEigenschaft)
    End If
Next

注意:把代码里的YourClassName替换成你当前类的实际名称。

两种方案都能解决问题,方案二更易读和维护,推荐优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:03:05