0

I have the following two programs

WindowsFormsApplication

ClassLibrary1 dll

The ClassLibrary1 dll is loaded to the Windowsform via appdomain loading. I have subscibed to the dll events through reflection across the appdomain. I am trying to subscribe to the dll action(TestAction) and also handle the action in windows forms. But I get this error 'Object of type 'System.EventHandler' cannot be converted to type 'System.Action'

This is the windows form code:

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;

namespace WindowsFormsApplication2
{
    [Serializable]
    public partial class Form1 : Form
    {
        void HandleEvent(object sender, EventArgs e)
        {
            Debug.WriteLine("HandleEvent called");
        }
        void HandleAction(object sender, EventArgs e)
        {
            Debug.WriteLine("HandleAction called");
        }
        public Form1()
        {
            InitializeComponent();
            Loader.Call(  "RaiseEvent", HandleEvent, DateTime.Now.ToShortDateString());
            Loader.Call( "RaiseAct", HandleAction, DateTime.Now.ToShortDateString());
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Application.Restart();
            Application.Run(new Form1());
            this.Close();
        }
    }

    public class Loader : MarshalByRefObject
    {
        static string dll = @"..\ConsoleApplication1\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
        static AppDomain ad = AppDomain.CreateDomain("Test");
        static Assembly a = Assembly.LoadFile(dll);
        static object o = a.CreateInstance("ClassLibrary1.Class1");
        static Type t = o.GetType();

        object CallInternal1( string method, EventHandler handler, object[] parameters)
        {
            // Subscribe to the event
            EventInfo eventInfo1 = t.GetEvent("TestEvent");
            eventInfo1.AddEventHandler(o, handler);

            MethodInfo m = t.GetMethod(method);
            return m.Invoke(o, parameters);
        }

        object CallInternal2( string method, EventHandler handler, object[] parameters)
        {
            // Subscribe to the event
            EventInfo eventInfo2 = t.GetEvent("TestAction");
            eventInfo2.AddEventHandler(o, handler);               // Error: Object of type 'System.EventHandler' cannot be converted to type 'System.Action

            MethodInfo m = t.GetMethod(method);
            return m.Invoke(o, parameters);
        }

        public static object Call( string method, EventHandler handler, params object[] parameters)
        {
            Loader ld = (Loader)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Loader).FullName);
            object result = 0;
            switch (method)
            {
                case "RaiseEvent":
                    {
                        result = ld.CallInternal1( method, handler, parameters);
                        break;
                    }

                case "RaiseAct":
                    {
                        result = ld.CallInternal2( method, handler, parameters);
                        break;
                    }
            }
            return result;
        }
    }
}

This is the ClassLibrary1.dll code

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;
        }



        public event Action<int> TestAction = Func;
        public int RaiseAct(string msg)
        {
            TestAction(3);
            return 5;
        }

        public static void Func(int a)
        {
            int g = 2;
        }

    }
}

1 Answers1

0

The type of the event is Action, so you can encapsulate the handler in an Action.

eventInfo2.AddEventHandler(o, new Action(() => handler(null, EventArgs.Empty)));

Update to the question in the comment, you can define a child class of EventArgs and pass it to the event handler.

class IntEventArgs : EventArgs { public int data; }
new Action<int>((index) => handler(null, new IntEventArgs{ data = index }))
shingo
  • 18,436
  • 5
  • 23
  • 42
  • Wouldn't the correct way to use `Delegate.CreateDelegate(eventInfo2.EventHandlerType, o, method))` as detailed in the duplicate I linked above? – Klaus Gütter Jan 12 '23 at 04:13
  • The way in the link creates the delegate with a `MethodInfo` instance, but in this question the thing to be registered is an `EventHandler` instance. – shingo Jan 12 '23 at 04:17
  • Thank you for replying. I have also included the dll codes. I tried your code. But I am getting this error: Object of type 'System.Action' cannot be converted to type 'System.Action`1[System.Int32]'. – Crystal Crystal Jan 12 '23 at 05:26
  • @CrystalCrystal I saw the error in your question is **System.Action** exactly, if you've changed the event type to **Action** later, you also need try the code with the new event type, it's flexible. – shingo Jan 12 '23 at 05:33
  • Thank you very much!!. It works. I modified it this way ```'eventInfo2.AddEventHandler(o, new Action((index) => handler(null, EventArgs.Empty)));'``` – Crystal Crystal Jan 12 '23 at 06:19
  • Could you also help me on one more thing? How do I access the value of 'index'? I am trying to get the value '3' from ClassLibrary1.dll and use it in the handler – Crystal Crystal Jan 12 '23 at 06:24
  • @CrystalCrystal Access in the event handler? Then check the update. – shingo Jan 12 '23 at 06:34