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

pwuypxnk  于 2023-01-14  发布在  其他
关注(0)|答案(2)|浏览(113)

我有一个winform应用程序(WindowsFormsApplication2),它使用appdomain加载dll。在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 = @"..\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.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;
        }

    }
}
aurhwmvo

aurhwmvo1#

您可以使用类似于以下内容的内容:

void HandleEvent(object sender, EventArgs e)
        {
            Debug.WriteLine("HandleEvent called");
        }

        string DLL = @"..\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.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"});

How do I use reflection to call a generic method?
Invoke a method of anonymous class
Subscribe to an event with Reflection
Invoke static methods

qzwqbdag

qzwqbdag2#

据我所知,您希望您的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());
}

请给我一个评论,如果这是从你试图实现的方式。

相关问题