通过反射调用成员,并将派生类作为参数传递 [英] Invoke member through reflection passing derived class as argument

查看:160
本文介绍了通过反射调用成员,并将派生类作为参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试调用类"CMyClass"的方法"MyMethod".此方法的参数类型为"CBaseClass",而我正在传递类型为"CDerivedClass"的对象.

I'm trying to call the method 'MyMethod' of class 'CMyClass'. This method has a parameter of type "CBaseClass", and I'm passing an object of type "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'.

The argument exception says "object of type 'MyNamespace.CDerivedClass' cannot be converted to type 'MyNamespace.CBaseClass'.

我在MyMethod签名中将"ByRef"更改为"ByVal",但未进行任何更改. 我试图通过以下方式更改"par"对象的类型:

I changed "ByRef" to "ByVal" in MyMethod signature, but nothing changed. I tried to change type of 'par' object with:

Dim par As CBaseClass = New CDerivedClass()

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

without success. How I can invoke correctly the method "MyMethod" with an instance of derived class? Thank you very much.

推荐答案

最后,我使用序列化解决了...

Finally I solved using serialization...

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

So 'par' is the string containing the serialized object of type CDerivedClass in the calling project.

MyMethod更改为:

MyMethod is changed to:

MyMethod(xml_CBaseClass As String)

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

In dll project the string parameter xml_CBaseClass is deserialized creating an object of CBaseClass.

注意:由于我有派生类型,派生类的反序列化带来了另一个问题.解决方案是 https://stackoverflow.com/a/590711/1315873 (我做了一些改动,使用StringWriter进行序列化,使用StringReader进行反序列化,而不是使用MemoryBuffer.)

Note: since I have derived type, Deserialization of derived class give another problem. The solution is https://stackoverflow.com/a/590711/1315873 (I just made a little change, using StringWriter for serialization, StringReader for deserialization, instead of using MemoryBuffer).

CBaseClass具有固定的派生类型,因此我将它们写为硬编码,但是要灵活一些,您可以执行以下操作:

CBaseClass has fixed derived types so I wrote them hard-coded, but to be flexible you can do something like:

    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().

CBaseClass and all its derivated classes must have constructor New() without parameters.

由于我不知道程序集的名称,所以我使用LoadFrom()来加载程序集(我使用Dir()从已知的固定文件夹中获取所有程序集).

I load assemblies using LoadFrom() since I don't know their names (I use Dir() to get all them from a known fixed folder).

这篇关于通过反射调用成员,并将派生类作为参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆