lundi 15 janvier 2018

Create event delegate to method with custom parameter

I'm struggling to get .Net Reflection to work with the following situation...

I'm writing a .Net 4.5.2 DLL that I can drop into an existing ASP.NET 4.5.2 production website, so I don't need to rebuild the website. In the new DLL I am using Reflection to find a class, add an event delegate and then call a method.

The problem I'm having is that the event delegate needs to bind to a local function with parameter class that also needs to be found via reflection.

In the existing DLL that cannot be rebuilt, I have the following (the following has been written by hand here, and is not copied, so might contain minor typos)...

Public Class OldClass
   ' A nested class used for the eventargs of the event
   Public Class OldClassEventArgs
     Public Property MiscArgs As String = ""
   End Class
   ' The event itself
   Public Event OldClassEvent
   ' 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

In the new DLL, I want to be able to create an instance of OldClass, bind an event handler to OldClassEvent and call OldClassMethod... with the result that the local event handler is called with the parameter being an instance of 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

As you can see in the above code, it's impossible for me to use OldClass.OldClassEventsArgs because it doesn't exist in the current context... only via reflection.

How can I create a method using a class found via reflection as a parameter??

Even if I have the local handler take ByVal e As Object I still get...

Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

... on the creation of the Delgate.





Aucun commentaire:

Enregistrer un commentaire