[C#Advanced] Dynamically register third-party library events for easy handling! Attached detailed steps and examples

[C#Advanced] Dynamically register third-party library events for easy handling! Attached detailed steps and examples

During the C#development process, we often need to handle various events, and sometimes we need to dynamically register events defined by third-party libraries. Today, I will share a Demo on how to dynamically register third-party library events, and explain each step in detail based on the provided code and comments.

最后更新 2/3/2024 10:57 PM
沙漠尽头的狼
预计阅读 7 分钟
分类
.NET
标签
.NET C# event registration

Hello everyone, I am a wolf at the end of the desert!

During the C#development process, we often need to handle various events, and sometimes we need to dynamically register events defined by third-party libraries. Today, I will share a Demo on how to dynamically register third-party library events, and explain each step in detail based on the provided code and comments. I hope that through this article, everyone can better grasp the method of dynamically registering events and bring more convenience to development work.

In C#, an event is a special member used to provide notification of changes in the state of a class or object. Sometimes, when we use third-party libraries, we need to dynamically register the events defined by these libraries so that appropriate actions can be performed when the event occurs.

Below, we will use a Demo to demonstrate how to dynamically register third-party library events.

1. Preparations

首先,我们需要一个第三方库的示例代码。在这个示例中,我们有一个名为ThirdLibrary的库,其中包含一个名为TestClass的类。这个类定义了几个事件和委托,我们将动态地为它们添加处理程序。

namespace ThirdLibrary;

public class TestClass
{
    /// <summary>
    /// 无参委托
    /// </summary>
    public Action? NoParamEvent;

    /// <summary>
    /// 带1个string参数
    /// </summary>
    public Action<string>? OneParamEvent;

    /// <summary>
    /// 带1个基本类型和自定义类型的委托
    /// </summary>
    public Action<string, EventParam>? TwoParamEvent;

    /// <summary>
    /// EventHandler事件
    /// </summary>
    public static event EventHandler<EventParam> EventHandlerEvent;

    public void CallEvent()
    {
        NoParamEvent?.Invoke();
        OneParamEvent?.Invoke("单参数委托");
        TwoParamEvent?.Invoke("2个参数委托调用成功", new EventParam() { Message = "帅哥,你成功调用啦!" });
        EventHandlerEvent?.Invoke(this, new EventParam { Message = "EventHandler事件调用成功"});
    }
}

/// <summary>
/// 自定义类型,注册时需要使用dynamic接收
/// </summary>
public class EventParam
{
    public string Message { get; set; }
}

2. Load a third-party library and create an instance

首先,我们使用Assembly.LoadFrom方法加载第三方库。然后,通过Assembly.GetType方法获取TestClass的类型,并使用Activator.CreateInstance方法创建其实例。

using System.Reflection;

// 加载第三方库  
var assembly = Assembly.LoadFrom("ThirdLibrary.dll");

// 创建TestClass的实例  
var testClassType = assembly.GetType("ThirdLibrary.TestClass");
var testClassInstance = Activator.CreateInstance(testClassType!);

3. Dynamic registration events

接下来,我们将通过反射动态地注册事件。首先,通过Type.GetFields方法获取TestClass类型的所有字段,并找到对应的事件字段。

var fields = testClassType!.GetFields();
  1. Register non-parametric delegation events

通过字段名称找到NoParamEvent字段,并使用FieldInfo.SetValue方法将事件处理程序方法EventHandlerMethod赋值给该字段。这样,当NoParamEvent事件被触发时,EventHandlerMethod方法将被调用。

// 1、获取NoParamEvent委托  
var noParamEventField = fields.First(field => "NoParamEvent" == field.Name);
noParamEventField.SetValue(testClassInstance, EventHandlerMethod);

// NoParamEvent事件处理程序方法  
void EventHandlerMethod()
{
    Console.WriteLine("NoParamEvent: event raised.");
}
  1. Register a delegate event with a string parameter

类似地,找到OneParamEvent字段,并将其设置为OneParamEventHandler方法。这个方法接受一个字符串参数,并打印一条消息。

// 2、获取OneParamEvent委托,并设置事件参数处理程序  
var oneParamEventField = fields.First(field => "OneParamEvent" == field.Name);
oneParamEventField.SetValue(testClassInstance, OneParamEventHandler);

// OneParamEvent事件处理程序方法,需要一个字符串参数  
void OneParamEventHandler(string param)
{
    Console.WriteLine($"OneParamEvent: event raised with parameter: {param}");
}
  1. Register a delegate event with two parameters

对于TwoParamEvent字段,我们将其设置为TwoParamEventHandler方法。由于第二个参数是自定义类型EventParam,我们无法在编译时知道其确切类型。因此,我们使用dynamic关键字作为参数类型,以便在运行时解析类型。

// 3、获取TwoParamEvent委托,并设置事件参数处理程序  
var twoParamEventField = fields.First(field => "TwoParamEvent" == field.Name);
twoParamEventField.SetValue(testClassInstance, TwoParamEventHandler);

// TwoParamEvent事件处理程序方法,需要两个参数:string和EventParam类型(通过反射传递,EventParam类型使用动态类型dynamic替换)  
void TwoParamEventHandler(string param1, dynamic param2) // 使用dynamic作为第二个参数的类型,并通过反射传递实际参数值  
{
    Console.WriteLine($"TwoParamEvent: event raised, param1={param1}, param2.Param1={param2.Message}");
}
  1. Register EventHandler events

对于EventHandlerEvent事件,我们使用Type.GetEvents方法获取事件信息,并通过EventInfo.EventHandlerType获取事件处理程序的类型。然后,我们创建一个EventHandler<dynamic>类型的委托,并使用Delegate.CreateDelegate方法创建一个与事件处理程序类型匹配的委托实例。最后,通过EventInfo.AddEventHandler方法将委托实例添加到事件中。

var events = testClassType.GetEvents();

// 4、获取EventHandler事件
var eventHandlerEventField = events.First(item => "EventHandlerEvent" == item.Name);
var eventHandlerType = eventHandlerEventField.EventHandlerType;
var eventHandlerMethod = new EventHandler<dynamic>(EventHandlerEventHandler);
var handle = Delegate.CreateDelegate(eventHandlerType, eventHandlerMethod.Method);
eventHandlerEventField.AddEventHandler(null, handle);

// EventHandler事件处理方法
void EventHandlerEventHandler(object sender, dynamic param)
{
    Console.WriteLine($"EventHandler: param.Param1={param.Message}");
}

4. Trigger events and verify registration

为了验证事件是否成功注册,我们调用TestClassCallEvent方法,该方法将触发所有已注册的事件。如果一切正常,我们将在控制台上看到相应的输出消息,证明事件处理程序被正确调用。

ThirdLibrary library method:

/// <summary>
/// 该方法用于触发事件,方便测试
/// </summary>
public void CallEvent()
{
    NoParamEvent?.Invoke();
    OneParamEvent?.Invoke("单参数委托");
    TwoParamEvent?.Invoke("2个参数委托调用成功", new EventParam() { Message = "帅哥,你成功调用啦!" });
    EventHandlerEvent?.Invoke(this, new EventParam { Message = "EventHandler事件调用成功" });
}

Trigger the above event:

// 5、模拟触发事件通知,测试事件是否注册成功
var callEventMethod = testClassType.GetMethods().First(method => "CallEvent" == method.Name);
callEventMethod.Invoke(testClassInstance, null);

The program output is as follows:

NoParamEvent: event raised.
OneParamEvent: event raised with parameter: 单参数委托
TwoParamEvent: event raised, param1=2个参数委托调用成功, param2.Param1=帅哥,你成功调用啦!
EventHandler: param.Param1=EventHandler事件调用成功

V. Summary

Through the above steps, we successfully dynamically registered the events defined by the third-party library. This approach is useful when dealing with unpredictable or unmodifiable third-party libraries because it allows us to dynamically add or remove event handlers at run time.

I hope this article can help you better understand how to dynamically register third-party library events and flexibly apply them in actual development. If you have any questions or suggestions, please leave a message at any time!

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 4/22/2026

Support for. NET by operating system versions (250707 update)

Use virtual machines and test machines to test the support of each version of the operating system for. NET. After installing the operating system, it is passed by measuring the corresponding running time of the installation and being able to run the Stardust Agent.

继续阅读
同分类 / 同标签 2/7/2026

Summary of experience in using AOT

From the very beginning of project creation, you should develop a good habit of conducting AOT release testing in a timely manner whenever new features are added or newer syntax is used.

继续阅读