我正在尝试调用类'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'的对象无法转换为'MyNamespace.CBaseClass'类型。
我在MyMethod签名中将“ByRef”更改为“ByVal”,但没有任何改变。 我尝试用:
更改'par'对象的类型Dim par As CBaseClass = New CDerivedClass()
没有成功。 如何使用派生类的实例正确调用方法“MyMethod”? 非常感谢你。
答案 0 :(得分:1)
我只是在一个独立的项目中尝试了你的代码,它运行良好。我只调整了装配线以获取当前程序集而不是文件,我更改了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
答案 1 :(得分:0)
最后我解决了使用序列化......
所以'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()从已知的固定文件夹中获取它们。)