Click here to Skip to main content
15,881,424 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
dll name is "RefTest.dll",code as below:

C#
using System;

namespace RefTest
{
    public class Test
    {
        public event Action<string> OnMessage;

        public void WriteString()
        {
            Console.WriteLine("Write String");
            OnMessage?.Invoke("ActionMessage");
        }
    }
}


Main Program as below:

C#
using System;
using System.Diagnostics;
using System.Reflection;

namespace ConsoleAppFixed
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom("RefTest.dll");      
            Type typeClass = assembly.GetType("RefTest.Test");            
            object obj = Activator.CreateInstance(typeClass);                  
            MethodInfo method = typeClass.GetMethod("WriteString"); 
            method.Invoke(obj, null);                                                     


            var t = typeof(Action<string>);
            Delegate mDelegate = Delegate.CreateDelegate(t, obj, "OnMessage");

            //I don't know how to register "OnMessage" event

            Console.ReadKey();
        }

        public static void Recieve()
        {
        }
    }
}


I don't know how to regist "OnMessage",any help will be appreciated,thank you!

What I have tried:

C#
var t = typeof(Action<string>);
 Delegate mDelegate = Delegate.CreateDelegate(t, obj, "OnMessage");

 //I don't know how to register "OnMessage"
Posted
Updated 8-Sep-20 16:09pm

The MS documentation already covers this:
How to: Hook Up a Delegate Using Reflection | Microsoft Docs[^]
C#
Assembly assembly = Assembly.LoadFrom("RefTest.dll");      
Type typeClass = assembly.GetType("RefTest.Test");            
object obj = Activator.CreateInstance(typeClass);                  

EventInfo messageEvent = typeClass.GetEvent("OnMessage");
MethodInfo receiveMethod = typeof(Program).GetMethod("Receive", BindingFlags.Public | BindingFlags.Static);
Delegate handler = Delegate.CreateDelegate(messageEvent.EventHandlerType, null, receiveMethod);
messageEvent.GetAddMethod().Invoke(obj, new[] { handler });

MethodInfo writeStringMethod = typeClass.GetMethod("WriteString"); 
writeStringMethod.Invoke(obj, null);
NB: You'll need to update your Receive method to match the expected signature of the event - eg:
C#
public static void Receive(string message) ...
You should also follow the naming[^] and design[^] guidelines for events as far as possible:
C#
public class Test
{
    public event EventHandler<string> Message;

    public void WriteString()
    {
        Console.WriteLine("Write String");
        Message?.Invoke(this, "ActionMessage");
    }
}
C#
public static void Receive(object sender, string message) { ... }
In an ideal world, the second argument to the event would be a class derived from System.EventArgs. But unless you can find a built-in one that suits your requirements, it could be tricky to create a custom class which is shared between the RefTest assembly and the calling assembly.
 
Share this answer
 
Comments
TabZhang 8-Sep-20 20:46pm    
Thanks Richard! Full follow up you suggestion, then Compilation pass,but running failed at "Delegate handler = Delegate.CreateDelegate(messageEvent.EventHandlerType, null, receiveMethod);"

System.ArgumentNullException : can not be null
Thanks Richard! I find use interface is a better way.

dll and MainProgram both can reference the Interface.

Interface Code:
C#
using System;

namespace MyInterface
{
    public interface ITestAction
    {
        string FailReason { get; set; }

        event Action<string> OnTestStart;

        void RunTest();

    }
}


DLL Code:
C#
using MyInterface;
using System;

namespace RefTest
{
    public class Test : ITestAction
    {
        public string FailReason { get; set; }

        public event Action<string> OnTestStart;

        public void RunTest()
        {
            try
            {
                Console.WriteLine("Write String");
                OnTestStart?.Invoke("ActionMessage");
            }
            catch (Exception ex)
            {
                FailReason = ex.Message;
            }
        }
    }
}


Main Program Code:
C#
using System;
using System.Reflection;
using MyInterface;

namespace ConsoleAppFixed
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom("RefTest.dll");
            Type typeClass = assembly.GetType("RefTest.Test");
            ITestAction obj = (ITestAction)Activator.CreateInstance(typeClass);

            if (obj != null)
            {
                obj.OnTestStart += ITestAction_OnTestStart;
                obj.RunTest();
            }

            Console.ReadKey();
        }

        private static void ITestAction_OnTestStart(string obj)
        {
            Console.WriteLine(obj);
        }


    }
}
 
Share this answer
 
v6

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900