【发布时间】:2018-01-15 12:00:44
【问题描述】:
我正在努力让 .Net Reflection 在以下情况下工作...
(下面是VB.Net,但我把它标记为C#,希望可以从更广泛的受众那里找到答案。如果C#答案无法转换为@987654324 @由于语言限制,至少我知道如果需要我可以在C#中重写它。)
我正在编写一个 .Net 4.5.2 DLL,我可以将它放入现有的 ASP.NET 4.5.2 生产网站,因此我不需要重建网站。在新的 DLL 中,我使用反射来查找一个类,添加一个事件委托,然后调用一个方法。
我遇到的问题是事件委托需要绑定到具有参数类的本地函数,该参数类也需要通过反射找到。
在现有的无法重建的DLL中,我有以下(这里是手写的,不是复制的,所以可能有轻微的错别字)...
Public Class OldClass
' A nested class used for the eventargs of the event
Public Class OldClassEventArgs
Inherits EventArgs
Public Property MiscArgs As String = ""
End Class
' Event delegate
Public Delegate Sub OldClassEventDelegate(ByVal e As OldClassEventsArgs)
' The event itself
Public Event OldClassEvent As OldClassEventDelegate
' A method that does things and then raises the event
Public Sub OldClassMethod(Byval arg1 As String)
RaiseEvent OldClassEvent(New OldClassEventArgs())
End Sub
End Class
在新的 DLL 中,我希望能够创建 OldClass 的实例,将事件处理程序绑定到 OldClassEvent 并调用 OldClassMethod...,结果是使用参数是OldClassEventArgs的实例...
Public Class MyPage
Inherits System.Web.UI.Page
Public Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Gets the assembly for the existing website DLL
Dim assem As Assembly = GetAssembly()
' Get the type of the class in the existing website
Dim oldClassType As Type = assem.GetType("OldClass", False, True)
' Create an instance of the class
Dim oldClassObj as Object = Activator.CreateInstance(oldClassType, False)
' Get the LOCAL event handler
Dim eventMethod As MethodInfo = Me.GetType().GetMethod("LocalEventHandler", BindingFlags.NonPublic Or BindingFlags.Instance)
' Get the event info
Dim eventInf As EventInfo = logonType.GetEvent("OldClassEvent")
' Create the delegate
Dim del As [Delegate] = [Delegate].CreateDelegate(eventInf.EventHandlerType, oldClassObj, eventMethod)
' Add the delegate to the event
eventInf.AddEventHandler(classObj, del)
' Get the method to call
Dim methodInf as MethodInfo = logonType.GetMethod("OldClassMethod", BindingFlags.Public Or BindingFlags.Instance)
' Call it
methodInf.Invoke(oldClassObj, New Object() { "foobar" })
End Sub
' The following CANNOT happen, because OldClassEventArgs needs to be found via reflection!
Protected Sub LocalEventHandler(ByVal e As OldClass.OldClassEventArgs)
' Do something with e.MiscArgs
End
End Class
正如您在上面的代码中看到的,我不可能使用OldClass.OldClassEventsArgs,因为它在当前上下文中不存在......只能通过反射。
如何使用通过反射找到的类作为参数创建方法?
即使我有本地处理程序采取ByVal e As Object 我仍然得到运行时错误...
无法绑定到目标方法,因为它的签名或安全透明度与委托类型的不兼容。
...关于Delgate的创建。
更新
基于@jmcilhinney 的cmets,我也尝试了以下方法声明(使用EventArgs),它仍然导致与以前相同的运行时错误...
Protected Sub LocalEventHandler(ByVal e As EventArgs)
End
【问题讨论】:
-
所有事件处理程序都应该有一个
sender类型的Object参数和一个e类型的EventArgs参数或派生类型。如果代码编写正确,那么OldClassEventArgs继承EventArgs并且您的方法可以声明为Protected Sub LocalEventHandler(sender As Object, e As EventArgs)并且它将起作用。 -
你说得对,应该有一个
sender参数,但在这种情况下,没有......你也是对的,事件 args 是继承自EventArgs(我将很快更新上面的代码以显示这一点)。但是,将方法更改为e As EventArgs仍然会导致相同的运行时错误消息 -
@jmcilhinney 我刚刚在
EventArgs之前重建了通过sender As Object的系统,结果对结果没有影响 -
能否不添加对旧程序集的引用以便直接使用其中的类?
-
不幸的是@Craig 那是不可能的......加上我现在有上面的代码工作,感谢 levent 提供的答案
标签: c# asp.net .net vb.net reflection