使用自定义参数创建事件委托给方法

时间:2018-01-15 12:00:44

标签: c# asp.net .net vb.net reflection

我努力让.Net反思能够解决以下问题...

(以下是VB.Net,但我已将此标记为C#,希望能够从更广泛的受众群体中找到答案。如果C#回答由于语言限制,无法转换为VB.Net,至少我知道如果需要,我可以在C#重新编写它。)

我正在编写.Net 4.5.2 DLL,我可以将其放入现有的ASP.NET 4.5.2生产网站,因此我不需要重建网站。在新的DLL中,我使用Reflection来查找一个类,添加一个事件委托,然后调用一个方法。

我遇到的问题是事件委托需要绑定到具有参数类的本地函数,该参数类也需要通过反射找到。

在现有的无法重建的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,因为它在当前上下文中并不存在...只能通过反射。

如何使用通过反射找到的类作为参数创建方法?

即使我有本地处理程序[{1}},我仍然会遇到运行时错误...

  

无法绑定到目标方法,因为其签名或安全透明度与委托类型的方法不兼容。

...创建ByVal e As Object

更新

基于@jmcilhinney的评论,我还尝试了以下方法声明(使用Delgate),它仍然会导致与之前相同的运行时错误...

EventArgs

1 个答案:

答案 0 :(得分:1)

创建委托实例时,我们需要使用包含委托方法的实例。

eventMethod => MethodInfo(LocalEventHandler)位于MyPage类上。

你需要改变

Dim del As [Delegate] = [Delegate].CreateDelegate(eventInf.EventHandlerType, oldClassObj, eventMethod)

Dim del As [Delegate] = [Delegate].CreateDelegate(eventInf.EventHandlerType, Me, eventMethod)