通过反射调用成员,传递派生类作为参数



我试图调用类'CMyClass'的方法'MyMethod'。这个方法有一个类型为"CBaseClass"的参数,我传递一个类型为"CDerivedClass"的对象。

Class CBaseClass
    Public m_AMember As String
    Sub MethodOne()
        // DoSomething
    End Sub
End Class
Class CDerivedClass
    Inherits CBaseClass
    Public m_MyMember As Integer
    Sub MethodTwo()
        // DoSomething
    End Sub
End Class
Class CMyClass
    Sub MyMethod(ByVal obj As CBaseClass)
        // DoSomething
    End Sub
End Class
Sub Main()
    'load assembly
    Dim objAssembly As Assembly = Assembly.LoadFrom("myfile.dll")
    'create class instance and MethodInfo object
    Dim t As Type = objAssembly.GetType("MyNamespace.CMyClass")
    Dim obj As Object = Activator.CreateInstance(t)
    Debug.Assert(obj IsNot Nothing)
    Dim m As MethodInfo = t.GetMethod("MyMethod")
    Debug.Assert(m IsNot Nothing)
    'Init arguments (only one)
    Dim par As New CDerivedClass()
    Dim parameters As Object() = New Object(0) {par}
    'invoke method
    m.Invoke(obj, parameters) '<<<< ArgumentException here!
End Sub

参数异常表示"MyNamespace类型的对象"。CDerivedClass'不能转换为' mynamespaces . cbaseclass '类型。

我在MyMethod签名中将"ByRef"更改为"ByVal",但没有任何更改。我尝试用:

改变'par'对象的类型
Dim par As CBaseClass = New CDerivedClass()

没有成功。我如何能正确调用方法"MyMethod"与派生类的实例?非常感谢。

我刚刚在一个独立的项目中尝试了你的代码,它工作得很好。我只调整了装配线以获取当前的程序集,而不是从文件中获取,并且我更改了GetType中的名称以反映我的名称空间。我的猜测是,也许你正在加载的DLL已经过期,或者你在调用程序集中有重复的类定义,这就是为什么它不能进行类型转换。

        Imports System.Reflection
    Module Module1
        Sub Main()
            'load assembly
            Dim objAssembly As Assembly = Assembly.GetExecutingAssembly()
            'create class instance and MethodInfo object
            Dim t As Type = objAssembly.GetType("ConsoleApplication1.CMyClass")
            Dim obj As Object = Activator.CreateInstance(t)
            Debug.Assert(obj IsNot Nothing)
            Dim m As MethodInfo = t.GetMethod("MyMethod")
            Debug.Assert(m IsNot Nothing)
            'Init arguments (only one)
            Dim par As New CDerivedClass()
            Dim parameters As Object() = New Object(0) {par}
            'invoke method
            m.Invoke(obj, parameters) '<<<< No ArgumentException here!
        End Sub
    End Module
    Class CBaseClass
        Public m_AMember As String
        Sub MethodOne()
        End Sub
    End Class
    Class CDerivedClass
        Inherits CBaseClass
        Public m_MyMember As Integer
        Sub MethodTwo()
        End Sub
    End Class
    Class CMyClass
        Sub MyMethod(ByVal obj As CBaseClass)
        End Sub
    End Class

最后我用序列化解决了…

所以'par'是包含调用项目中CDerivedClass类型的序列化对象的字符串。

MyMethod更改为:

MyMethod(xml_CBaseClass As String)

在dll项目中,字符串参数xml_CBaseClass被反序列化,创建CBaseClass的对象。

注意:既然我有了派生类型,派生类的反序列化就会产生另一个问题。解决方案是https://stackoverflow.com/a/590711/1315873(我只是做了一点改变,使用StringWriter进行序列化,使用StringReader进行反序列化,而不是使用MemoryBuffer)

CBaseClass有固定的派生类型,所以我把它们写在硬编码中,但为了灵活,你可以这样做:

    Dim subTypes as New List(Of Type) '<- all classes derived from 'myType'
    For Each t In myType.Assembly.GetTypes()
        If t.IsSubclassOf(myType) Then
            subTypes.Add(t)
        End If
    Next

CBaseClass及其所有派生类必须具有不带参数的构造函数New()。

我使用LoadFrom()加载程序集,因为我不知道它们的名称(我使用Dir()从已知的固定文件夹中获取所有它们)。

相关内容

  • 没有找到相关文章

最新更新