Exception unhandled when event is raised in dll (accessed using app domain)

Crystal98 1 Reputation point
2022-12-01T05:51:01.253+00:00

My project contains

windows form application(WindowsFormsApplication1)
dll (ClassLibrary1).
I am trying to implement some logic in my windows form application when an event is raised in my DLL. I am accessing DLL methods through AppDomain.

Below is the code in windows form Form1.cs
using System;
// more usings ...
using ClassLibrary1;
using System.Reflection;

namespace WindowsFormsApplication1  
{  
    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            trial obj = new trial();  
            obj.trial1();  
         }  
      }  
  
    class trial   
    {  
        void HandleEvent(object sender, EventArgs e)  
        {  
            Console.WriteLine("HandleEvent called");  
        }  
  
         AppDomain ad = AppDomain.CreateDomain("Test");  
         string DLL = @"C:\..\ClassLibrary1.dll";  
              
           public void trial1()  
            {  
                 trial pro = new trial();MethodInfo method = typeof(trial).GetMethod("HandleEvent", BindingFlags.NonPublic | BindingFlags.Instance);  
  
                // Subscribe to the event  
                EventInfo eventInfo = typeof(ClassLibrary1.Class1).GetEvent("TestEvent");  
                Type type = eventInfo.EventHandlerType;  
                Delegate handler = Delegate.CreateDelegate(type, pro, method);  
                // method call 1  
                Loader.Call(ad, DLL,"ClassLibrary1.Class1","RaiseEvent",DateTime.Now.ToShortDateString());  
            }  
    }  
  
    public class Loader : MarshalByRefObject  
    {  
        object CallInternal(string dll, string typename, string method, object[] parameters)  
        {  
            Assembly a = Assembly.LoadFile(dll);  
            object o = a.CreateInstance(typename);  
            Type t = o.GetType();  
            MethodInfo m = t.GetMethod(method);  
            return m.Invoke(o, parameters);  
        }  
  
        public static object Call(AppDomain domain, string dll, string typename, string method, params object[] parameters)  
        {  
            Loader ld = (Loader)domain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Loader).FullName);  
            object result = ld.CallInternal(dll, typename, method, parameters);  
            AppDomain.Unload(domain);  
            return result;  
        }  
    }  
}  

Below is the code in ClassLibrary1.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassLibrary1  
{  
    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;  
         }  
    }  
}  

It throws an exception when it runs TestEvent(this, EventArgs.Empty); The exception is 'Object reference not set to an instance of an object.'
There are no issues when accessing the same event using a console application program. The code in the console application program are as follows.
using System;
using System.Reflection;

class Test  
{  
    void HandleEvent(object sender, EventArgs e)  
    {  
        Console.WriteLine("HandleEvent called");  
    }  
  
    static void Main()  
    {  
        Test test = new Test();  
        ClassLibrary1.Class1 publisher = new ClassLibrary1.Class1();  
        MethodInfo method = typeof(Test).GetMethod("HandleEvent", BindingFlags.NonPublic | BindingFlags.Instance);  
  
        // Subscribe to the event  
        EventInfo eventInfo = typeof(ClassLibrary1.Class1).GetEvent("TestEvent");  
        Type type = eventInfo.EventHandlerType;  
        Delegate handler = Delegate.CreateDelegate(type, test, method);  
  
        eventInfo.AddEventHandler(publisher, handler);  
        publisher.RaiseEvent("hello");  
    }  
}  

Any help will be very much appreciated. Thank you.

Developer technologies C#
{count} votes

2 answers

Sort by: Most helpful
  1. Jack J Jun 25,296 Reputation points
    2022-12-01T08:58:49.477+00:00

    @Crystal98 , Welcome to Microsoft Q&A, based on my test, I get the same error with you.

    I find that you used another method to call the method in the winform app. However, I noted that you only called the RaiseEvent method and you didn't add the event handler.

    I make some changes and you could have a look.

    public void trial1()  
            {  
                trial pro = new trial();   
                MethodInfo method = typeof(trial).GetMethod("HandleEvent", BindingFlags.NonPublic | BindingFlags.Instance);  
                Class1 publisher = new Class1();               //->here add it  
                // Subscribe to the event  
                EventInfo eventInfo = typeof(ClassLibrary1.Class1).GetEvent("TestEvent");  
                Type type = eventInfo.EventHandlerType;  
                Delegate handler = Delegate.CreateDelegate(type, pro, method);  
                eventInfo.AddEventHandler(publisher, handler);    //->here add it  
                publisher.RaiseEvent("Hello");                                  //->here add it  
              
            }  
    

    Hope my code could help you.

    Best Regards,
    Jack


    If the answer is the right solution, please click "Accept Answer" and upvote it.If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Viorel 122.6K Reputation points
    2022-12-01T09:00:50.243+00:00

    It depends on what do you what to achieve and how to distribute the objects between domains.

    For example, try this:

    [Serializable]  
    class trial  
    {  
        void HandleEvent( object sender, EventArgs e )  
        {  
            Console.WriteLine( "HandleEvent called" );  
        }  
      
        AppDomain ad = AppDomain.CreateDomain( "Test" );  
        string DLL = @"....\ClassLibrary1.dll";  
      
        public void trial1( )  
        {  
            Loader.Call( ad, DLL, "ClassLibrary1.Class1", "RaiseEvent", HandleEvent, DateTime.Now.ToShortDateString( ) );  
        }  
    }  
      
    public class Loader : MarshalByRefObject  
    {  
        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( AppDomain domain, string dll, string typename, string method, EventHandler handler, params object[] parameters )  
        {  
            Loader ld = (Loader)domain.CreateInstanceAndUnwrap( Assembly.GetExecutingAssembly( ).FullName, typeof( Loader ).FullName );  
            object result = ld.CallInternal( dll, typename, method, handler, parameters );  
            AppDomain.Unload( domain );  
            return result;  
        }  
    }  
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.