如何捕获dll事件返回的参数(使用反射订阅事件)?



我有一个使用appdomain加载dll的winform应用程序(WindowsFormsApplication2)。在winform中,我订阅了ClassLibrary.dll中实现的"TestEvent"。如果TestEvent返回一个参数,我如何在winform中实现的事件处理程序HandleEvent中捕获返回的参数?

这是winform应用程序代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Diagnostics;
using ClassLibrary1;
using static System.Net.Mime.MediaTypeNames;
namespace WindowsFormsApplication2
{

[Serializable]
public partial class Form1 : Form
{
void HandleEvent(object sender, EventArgs e)
{
Debug.WriteLine("HandleEvent called");
}
string DLL = @"..ConsoleApplication1ClassLibrary1binDebugClassLibrary1.dll";
public Form1()
{
InitializeComponent();
Loader.Call( DLL, "ClassLibrary1.Class1", "RaiseEvent", HandleEvent, DateTime.Now.ToShortDateString());
}
private void button1_Click(object sender, EventArgs e)
{
Application.Restart();
Application.Run(new Form1());
this.Close();
}

}
public class Loader : MarshalByRefObject
{
AppDomain ad = AppDomain.CreateDomain("Test");
object CallInternal(string dll, string typename, string method, EventHandler handler, object[] parameters)
{
Assembly a = Assembly.LoadFile(dll);
object o = a.CreateInstance(typename);
Type t = o.GetType();
// Subscribe to the event
EventInfo eventInfo = t.GetEvent("TestEvent");
eventInfo.AddEventHandler(o, handler);
MethodInfo m = t.GetMethod(method);
return m.Invoke(o, parameters);
}
public static object Call( string dll, string typename, string method, EventHandler handler, params object[] parameters)
{
Loader ld = (Loader)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Loader).FullName);
object result = ld.CallInternal(dll, typename, method, handler, parameters);
AppDomain.Unload(ad);
return result;
}
}
}

这是ClassLibrary1.dll代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassLibrary1
{
[Serializable]
public class Class1
{
public event EventHandler TestEvent;
public int RaiseEvent(string msg)
{
try
{
TestEvent(this, EventArgs.Empty);
}
catch (Exception ex)
{
Console.WriteLine("the exception is: " + ex.ToString());
if (ex.InnerException != null)
{
Console.WriteLine("the inner exception is: " + ex.InnerException.Message.ToString());
}
}
return 2;
}
}
}

你可以这样写:

void HandleEvent(object sender, EventArgs e)
{
Debug.WriteLine("HandleEvent called");
}
string DLL = @"..ConsoleApplication1ClassLibrary1binDebugClassLibrary1.dll";    
//You can can create new appDomain: var dom = AppDomain.CreateDomain("domain name");//If you really need it!
var dom = AppDomain.CurrentDomain;
var assembly = dom.Load(DLL);
var type = assembly.GetTypes().FirstOrDefault(p => p.FullName == "ClassLibrary1.Class1");
var inst = Activator.CreateInstance(type);
var eventInfo = type.GetEvent("event name");
var handleEventMethod = GetType().GetMethod("HandleEvent");
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, type, handleEventMethod);
eventInfo.AddEventHandler(inst, handler);

var method = type.GetMethod("RaiseEvent");
var resultData = (int)method.Invoke(inst, new object[]{"Expecting argument of your method"});

如何使用反射来调用泛型方法?

调用匿名类

的方法使用反射订阅事件

调用静态方法

根据我的理解,您希望您的HandleEvent方法能够消费或产生一些我们称之为Argument的自定义值。在这种情况下,结果可以通过继承自定义事件的EventArgs来实现。

public class Class1
{
public event ValueReceivedEventHandler TestEvent;
public int RaiseEvent(string msg)
{
try
{
TestEvent?.Invoke(
this, 
new ValueReceivedEventArgs{ Argument = msg } );
}
catch (Exception ex)
{
Console.WriteLine("the exception is: " + ex.ToString());
if (ex.InnerException != null)
{
Console.WriteLine("the inner exception is: " + ex.InnerException.Message.ToString());
}
}
return 2;
}
}

自定义事件参数类

public delegate void ValueReceivedEventHandler(Object sender, ValueReceivedEventArgs e);
public class ValueReceivedEventArgs : EventArgs
{
public object Argument { get; set; }
}

您可以通过以下方式处理事件:

void HandleEvent(object sender, EventArgs e)
{
if(e is ValueReceivedEventArgs ePlus)
{
Debug.WriteLine(ePlus.Argument.ToString());
}
}

void HandleEvent(object sender, ValueReceivedEventArgs e)
{
Debug.WriteLine(e.Argument.ToString());
}

如果这与你想要达到的目标相去甚远,请给我留下评论。

最新更新