【问题标题】:Dynamically generated generic type not working properly动态生成的泛型类型无法正常工作
【发布时间】:2020-08-19 10:08:13
【问题描述】:

以下代码可以正常工作:

 Dim SubmodelElement = New BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.[Property](Of Double)() With {
                .IdShort = "TestProperty1",
                .[Set] = Function(prop, val)
                             Return _test = val
                         End Function
        }
    SubmodelElement.[Get] = Function(prop)
                                Return 4711
                            End Function

我要做的是使用以下代码为我的类的每个属性动态创建这些子模型元素:

For Each Eigenschaft As PropertyInfo In Me.GetType().GetProperties()
            If Eigenschaft.CanRead = True Then
                Dim Eigenschaftstyp As Type = Type.GetType(Eigenschaft.PropertyType.FullName)

                Dim GenerischerTypBasysProperty As Type = GetType(BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property(Of)).MakeGenericType(Eigenschaftstyp)
                Dim BasysEigenschaft = Activator.CreateInstance(GenerischerTypBasysProperty)

                BasysEigenschaft.IdShort = Eigenschaft.Name
                BasysEigenschaft.[Get] = Function(prop)
                                             'Return Eigenschaft.GetValue(Me)
                                             Return 4711
                                         End Function
                BasysEigenschaft.Set = Sub(ByVal Prop, ByVal Wert)
                                           Eigenschaft.SetValue(Me, Wert)
                                       End Sub
                MyBase.SubmodelElements.Add(BasysEigenschaft)
            End If
        Next

在调试器中可以看到两个对象(SubmodelElement 和 BasysEigenschaft 属于同一类型)。

screenshot of values of submodelElement and BasysEigenschaft

不幸的是,[Get] 函数的分配在第二个代码片段中不起作用。我收到此错误

System.InvalidCastException:“方法调用失败,因为 'Public Overrides Property Get() As BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes.GetPropertyValueHandler(Of Double)' 无法使用这些参数调用: 参数匹配参数 'value' 无法从 'VB$AnonymousDelegate_0(Of Object,Integer)' 转换为 'GetPropertyValueHandler(Of Double)'。"

screenshot of error message

任何帮助将不胜感激

【问题讨论】:

  • 我是否可以添加任何其他信息以更轻松地帮助我解决此问题? C#-answers 也被接受..
  • 您还应该包括Property 的定义,特别是因为Get 的确切签名在这里很重要。
  • 话虽如此,一些人对此表示怀疑,一旦你进入构造类型的世界,VB 就会停止在 Function(Of T) 等和相应的委托类型之间进行大量方便的转换,并且您将不得不自己构建委托。
  • 此 Microsoft 链接可能包含一些有用的信息,请记住,您必须将事件/处理程序连接转换为您真正想要做的事情:docs.microsoft.com/en-us/dotnet/framework/…
  • 请注意,在 FunctionSub lambdas 中的参数上使用默认的 Object 类型并不是一个好习惯;由于您的使用,您不会获得类型推断,并且您可能需要使这些类型完全正确才能正常工作。

标签: .net vb.net generics .net-core reflection


【解决方案1】:

我与 SubmodelElemenntTypes.Property -Class 的创建者讨论了这个问题。 像 Craig 建议的 Activator.CreateInstance-method 不会创建与 new Property (of T) 构造函数完全相同的类型。以下几行解决了这些问题。

        For Each Eigenschaft As PropertyInfo In Me.GetType().GetProperties()

        If Eigenschaft.GetCustomAttributes(Of BasysPropertyAttribute).Count > 0 Then

            If Eigenschaft.CanRead = True Then


                If Eigenschaft.CanRead = True Then
                    Dim Eigenschaftstyp As Type = Type.GetType(Eigenschaft.PropertyType.FullName)

                    Dim BasysDataTypeXsd As DataType = DataType.GetDataTypeFromSystemType(Eigenschaftstyp)
                    Dim BasysEigenschaft As BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property = DirectCast(SubmodelElementFactory.CreateSubmodelElement(ModelType.Property, BasysDataTypeXsd), BaSyx.Models.Core.AssetAdministrationShell.Implementations.SubmodelElementTypes.Property)


                    BasysEigenschaft.IdShort = Eigenschaft.Name
                    BasysEigenschaft.[Get] = Function(BasysProperty As Object)
                                                 Return New ElementValue(Eigenschaft.GetValue(Me), BasysDataTypeXsd)
                                             End Function
                    BasysEigenschaft.[Set] = Sub(ByVal BasysProperty As Object, ByVal Wert As ElementValue)
                                                 Eigenschaft.SetValue(Me, CTypeDynamic(TypeDescriptor.GetConverter(Eigenschaftstyp).ConvertFromString(Nothing, Globalization.CultureInfo.InvariantCulture, Wert.Value), Type.GetType(Eigenschaft.PropertyType.FullName)))
                                             End Sub
                    MyBase.SubmodelElements.Add(BasysEigenschaft)

                End If


            End If

        End If

    Next

感谢克雷格的帮助!

【讨论】:

  • 不客气,我很高兴得知您能够解决问题。
猜你喜欢
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
相关资源
最近更新 更多