TabZhang Ответов: 2

Как отразить одну DLL и зарегистрировать ее действие<string> event


имя dll-это "RefTest.dll",код, как показано ниже:

using System;

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

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


Основная программа как показано ниже:

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()
        {
        }
    }
}


Я не знаю,как зарегистрировать "OnMessage", любая помощь будет оценена по достоинству, спасибо!

Что я уже пробовал:

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

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

2 Ответов

Рейтинг:
4

TabZhang

Спасибо, Ричард! Я считаю, что использование интерфейса-это лучший способ.

dll и MainProgram оба могут ссылаться на интерфейс.

Код Интерфейса:

using System;

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

        event Action<string> OnTestStart;

        void RunTest();

    }
}


DLL-код:
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;
            }
        }
    }
}


Основной Программный Код:
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);
        }


    }
}


Рейтинг:
16

Richard Deeming

Документация MS уже охватывает это:
Как подключить делегат, используя отражение, Майкрософт документы[^]

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: Вам нужно будет обновить свой Receive метод для соответствия ожидаемой сигнатуре события - например:
public static void Receive(string message) ...
Вы также должны следовать называющий[^] и дизайн[^] руководящие принципы для проведения мероприятий, насколько это возможно:
public class Test
{
    public event EventHandler<string> Message;

    public void WriteString()
    {
        Console.WriteLine("Write String");
        Message?.Invoke(this, "ActionMessage");
    }
}
public static void Receive(object sender, string message) { ... }
В идеальном мире вторым аргументом для события был бы класс, производный от System.EventArgs Но если вы не можете найти встроенный, который соответствует вашим требованиям, может быть сложно создать пользовательский класс, который является общим для всех пользователей. RefTest сборка и вызывающая сборка.


TabZhang

Спасибо, Ричард! Полное следование вашему предложению, затем проход компиляции,но запуск не удался в "Delegate handler = Delegate.CreateDelegate(messageEvent.EventHandlerType, null, receiveMethod);"

Система.ArgumentNullException : не может быть null