From ff6832eb1850db6b18d15251287dd9cbc8f47a73 Mon Sep 17 00:00:00 2001 From: ls9512 <598914653@qq.com> Date: Wed, 26 Jul 2023 16:44:59 +0800 Subject: [PATCH] 1. Fix some bugs 2. Performance optimization --- .github/README.md | 179 ++++++++++-------- .github/README_CN.md | 178 +++++++++-------- CSharp/Script/Attribute/Base.meta | 8 + .../Attribute/Base/EventAttributeBase.cs | 17 ++ .../Attribute/Base/EventAttributeBase.cs.meta | 11 ++ CSharp/Script/Attribute/EventEnumAttribute.cs | 2 +- CSharp/Script/Attribute/ListenAttribute.cs | 8 +- .../Script/Attribute/ListenGroupAttribute.cs | 10 +- .../Script/Attribute/ListenTypeAttribute.cs | 6 +- CSharp/Script/EventListener.cs | 68 +++---- package.json | 2 +- 11 files changed, 275 insertions(+), 214 deletions(-) create mode 100644 CSharp/Script/Attribute/Base.meta create mode 100644 CSharp/Script/Attribute/Base/EventAttributeBase.cs create mode 100644 CSharp/Script/Attribute/Base/EventAttributeBase.cs.meta diff --git a/.github/README.md b/.github/README.md index 91195fe..0d8b180 100644 --- a/.github/README.md +++ b/.github/README.md @@ -14,62 +14,63 @@ > Official QQ Group:[1070645638](https://jq.qq.com/?_wv=1027&k=ezkLnUln) - -* 1. [Introduction](#Introduction) - * 1.1. [Environment](#Environment) - * 1.2. [Folder](#Folder) - * 1.3. [Feature](#Feature) - * 1.4. [Structure](#Structure) - * 1.5. [Rules / Recommendations](#RulesRecommendations) - * 1.6. [Start](#Start) -* 2. [Component](#Component) - * 2.1. [Event Manager](#EventManager) - * 2.2. [Event Dispatcher](#EventDispatcher) - * 2.3. [Event Listener](#EventListener) - * 2.4. [Object Listener](#ObjectListener) - * 2.5. [Unity MonoListener](#UnityMonoListener) - * 2.6. [Event Handler](#EventHandler) - * 2.6.1. [EventHandler](#EventHandler-1) - * 2.6.2. [EventHandler\](#EventHandlerT) -* 3. [Optional Attribute](#OptionalAttribute) - * 3.1. [ EventEnumAttribute](#EventEnumAttribute) - * 3.2. [ListenAttribute](#ListenAttribute) - * 3.3. [ListenTypeAttribute](#ListenTypeAttribute) - * 3.4. [ListenGroupAttribute](#ListenGroupAttribute) -* 4. [API](#API) - * 4.1. [Event Definition](#EventDefinition) - * 4.2. [Auto Listener](#AutoListener) - * 4.3. [Manual Listener](#ManualListener) - * 4.4. [Listen Event](#ListenEvent) - * 4.5. [Listen Event Type](#ListenEventType) - * 4.6. [Listen Group](#ListenGroup) - * 4.7. [Maunal Register / Deregister Event](#MaunalRegisterDeregisterEvent) - * 4.8. [Dispatch Event](#DispatchEvent) - * 4.9. [Dispatch Event (Thread Safety for Unity)](#DispatchEventThreadSafetyforUnity) - * 4.10. [Dispatch to Target](#DispatchtoTarget) - * 4.11. [Dispatch to Group](#DispatchtoGroup) - * 4.12. [Full API](#FullAPI) -* 5. [Compatibility Features](#CompatibilityFeatures) - * 5.1. [Compatibility List](#CompatibilityList) - * 5.2. [string Event](#stringEvent) - * 5.3. [class / struct Event](#classstructEvent) - - - -## 1. Introduction -### 1.1. Environment + + +- [UEvent](#uevent) + - [1 Introduction](#1-introduction) + - [1.1 Environment](#11-environment) + - [1.2 Folder](#12-folder) + - [1.3 Feature](#13-feature) + - [1.4 Structure](#14-structure) + - [1.5 Rules / Recommendations](#15-rules--recommendations) + - [1.6 Start](#16-start) + - [2 Component](#2-component) + - [2.1 Event Manager](#21-event-manager) + - [2.2 Event Dispatcher](#22-event-dispatcher) + - [2.3 Event Listener](#23-event-listener) + - [2.4 Object Listener](#24-object--listener) + - [2.5 Unity MonoListener](#25-unity-monolistener) + - [2.6 Event Handler](#26-event-handler) + - [2.6.1 EventHandler](#261-eventhandler) + - [2.6.2 EventHandler\](#262-eventhandlert) + - [3 Optional Attribute](#3-optional-attribute) + - [3.1 EventEnumAttribute](#31-eventenumattribute) + - [3.2 ListenAttribute](#32-listenattribute) + - [3.3 ListenTypeAttribute](#33-listentypeattribute) + - [3.4 ListenGroupAttribute](#34-listengroupattribute) + - [4 API](#4-api) + - [4.1 Event Definition](#41-event-definition) + - [4.2 Auto Listener](#42-auto-listener) + - [4.3 Manual Listener](#43-manual-listener) + - [4.4 Listen Event](#44-listen-event) + - [4.5 Listen Event Type](#45-listen-event-type) + - [4.6 Listen Group](#46-listen-group) + - [4.7 Maunal Register / Deregister Event](#47-maunal-register--deregister-event) + - [4.8 Dispatch Event](#48-dispatch-event) + - [4.9 Dispatch Event (Thread Safety for Unity)](#49-dispatch-event-thread-safety-for-unity) + - [4.10 Dispatch to Target](#410-dispatch-to-target) + - [4.11 Dispatch to Group](#411-dispatch-to-group) + - [4.12 Full API](#412-full-api) + - [5 Compatibility Features](#5-compatibility-features) + - [5.1 Performance Optimization](#51-performance-optimization) + - [5.1.1 Preloading](#511-preloading) + - [5.2 Compatibility List](#52-compatibility-list) + - [5.3 \>string Event](#53-string-event) + - [5.4 class / struct Event](#54-class--struct-event) + + + +## 1 Introduction +### 1.1 Environment ![Unity: 2019.4.3f1](https://img.shields.io/badge/Unity-2017+-blue) ![.NET 4.x](https://img.shields.io/badge/.NET-4.x-blue) -### 1.2. Folder +### 1.2 Folder * **Samples**: Example folder. It can be deleted in the you project to reduce space consumption. * **CSharp**: The core fully implemented by .Net, can be used independently in .Net environment. * **Unity**: The additional functions implemented by unity class library, you need to work with the code in the core folder when working in unity environment. -### 1.3. Feature +### 1.3 Feature * Support to define multiple groups of events through enumeration, and monitor by single event or by event type. * At the same time, it supports enum / string / class / struct type event definition to minimize changes and be compatible with different projects. * Support receiving event priority. @@ -78,12 +79,12 @@ * It also supports common methods and delegated methods. * Provide the `ObjectListener` and `MonoListener` base classes, so that any class can automatically register/remove listeners, and you can also implement the `IEventListener` interface yourself. -### 1.4. Structure +### 1.4 Structure * **EventManager** -> **EventDispatcher**-> **EventHandler** * Internal implementation : **EventListener** -> **EventDispatcher** * External implementation : **UserEventListener** -### 1.5. Rules / Recommendations +### 1.5 Rules / Recommendations * For each type of event, use an enumerated type such as AppEvent, GameEvent, etc. Each event type corresponds to an event dispatcher instance. * It is possible to use only one event type per project, but it is not recommended. * Method-type listener needs to specify the binding object, while delegate-type listener does not need to specify the object. @@ -93,30 +94,30 @@ * **enum** / **string** type events use the **UEvent** interface, **class** / **struct** type events use the **UEvent\** interface, the interface does not do Complete type constraints, but be sure to call in accordance with the convention to avoid unexpected problems. * Although multiple types of events are supported at the same time, it is still strongly recommended to use only one type of event format in a project. -### 1.6. Start +### 1.6 Start Copy `Events` folder into `UnityProject/Assets/Plugins/`. *** -## 2. Component +## 2 Component -### 2.1. Event Manager +### 2.1 Event Manager Used to manage all event dispatchers. -### 2.2. Event Dispatcher +### 2.2 Event Dispatcher Used to manage listener registration/de-registeration and event dispatcher for a specific event type. -### 2.3. Event Listener +### 2.3 Event Listener Used to manage the event listener registration/de-registration of a specified object. -### 2.4. Object Listener +### 2.4 Object Listener The user class implements the event mechanism by inheriting the class or initializing the class by itself, which can automatically register and de-register the object, and provide quick-call listener registration, removal, and event distribution interfaces. -### 2.5. Unity MonoListener +### 2.5 Unity MonoListener Same as ObjectListener's interface,uesd for MonoBehaviour GameObject. -### 2.6. Event Handler -#### 2.6.1. EventHandler +### 2.6 Event Handler +#### 2.6.1 EventHandler |Property|Description|Remarks| |-|-|-| |Type|Event definition object type|Event definition `enum/string/class/struct` and other objects Type, equivalent to `typeof(X)`| @@ -128,7 +129,7 @@ Same as ObjectListener's interface,uesd for MonoBehaviour GameObject. |Method|Listen method|For the non-parameter delegated listening, the delegate will be automatically converted to MehtodInfo for execution| |Parameters|Parameters of the listen method|| |Action|Listen delegate Action|| -#### 2.6.2. EventHandler\ +#### 2.6.2 EventHandler\ |Property|Description|Remarks| |-|-|-| |ActionT|Listen delegate Action\|| @@ -137,11 +138,11 @@ Same as ObjectListener's interface,uesd for MonoBehaviour GameObject. *** -## 3. Optional Attribute +## 3 Optional Attribute -### 3.1. EventEnumAttribute +### 3.1 EventEnumAttribute This attribute is a reserved function, and it may be used to automatically acquire event definitions scattered in different assemblies by reflection in the later stage. Currently, it has no function. -### 3.2. ListenAttribute +### 3.2 ListenAttribute It is used to mark the method that needs to listen the specified event in class. The event listener will automatically search for all methods containing this attribute and register for listen. * **Property** @@ -154,14 +155,14 @@ The event listener will automatically search for all methods containing this att * Must be an instance object. * Must be a non-static method. -### 3.3. ListenTypeAttribute +### 3.3 ListenTypeAttribute The method with this attribute can receive all events of the specified event type, traverse all enumerations and register all listeners. * **Property** * **Type** : Event enum type * **Priority** : Priority * **Interrupt** : Interrupt event queue -### 3.4. ListenGroupAttribute +### 3.4 ListenGroupAttribute The event will only be triggered when the event sent through the `DispatchGroup` interface corresponds to the group in the attribute tag. * **Property** * **Type** : Event type @@ -174,9 +175,9 @@ The event will only be triggered when the event sent through the `DispatchGroup` *** -## 4. API +## 4 API -### 4.1. Event Definition +### 4.1 Event Definition ``` cs /* UEvent recommends using enumeration types to define events, and implement event grouping functions through different enumerations. @@ -192,7 +193,7 @@ public enum GameEventType } ``` -### 4.2. Auto Listener +### 4.2 Auto Listener ``` cs // Any C# class gains monitoring capabilities. public class TestClass : EventListener @@ -205,7 +206,7 @@ public class UnityTestClass : MonoEventListener } ``` -### 4.3. Manual Listener +### 4.3 Manual Listener ``` cs // Generate a listener for the specified object, executed when the general object is generated. var listener = new EventListener(this); @@ -217,7 +218,7 @@ EventListener.Register(); EventListener.DeRegister(); ``` -### 4.4. Listen Event +### 4.4 Listen Event ``` cs // Listen to a single event, no priority. [Listen(GameEvent.GameStart)] @@ -238,7 +239,7 @@ public void TestMethod() } ``` -### 4.5. Listen Event Type +### 4.5 Listen Event Type ``` cs [ListenType(typeof(GameEvent))] public void TestMethod() @@ -246,7 +247,7 @@ public void TestMethod() } ``` -### 4.6. Listen Group +### 4.6 Listen Group ``` cs [ListenGroup(GameEvent.GameStart, "Player")] public void TestMethod() @@ -254,7 +255,7 @@ public void TestMethod() } ``` -### 4.7. Maunal Register / Deregister Event +### 4.7 Maunal Register / Deregister Event ``` cs // Add listener UEvent.Listen(eventType, this, methodInfo, group, priorty, interrupt); @@ -272,29 +273,29 @@ UEvent.Remove(eventType, this, method); UEvent.Remove(eventType, action); ``` -### 4.8. Dispatch Event +### 4.8 Dispatch Event ``` cs UEvent.Dispatch(eventType, args); ``` -### 4.9. Dispatch Event (Thread Safety for Unity) +### 4.9 Dispatch Event (Thread Safety for Unity) ``` cs // This interface will delegate events to the Unity main thread for execution, only available in Unity extensions. UEvent.DispatchSafe(eventType, args); ``` -### 4.10. Dispatch to Target +### 4.10 Dispatch to Target ``` cs UEvent.DispatchTo(eventType, target, args); ``` -### 4.11. Dispatch to Group +### 4.11 Dispatch to Group ``` cs // If the `Group` parameter is empty, it is equivalent to calling the `Dispatch` interface, and the event will be sent to any listener method without a group. UEvent.DispatchGroup(eventType, group, args); ``` -### 4.12. Full API +### 4.12 Full API If you want to get the complete function of **UEvent** or call the internal interface, you can call it by using the following methods. The interface is slightly different from the quick call interface mentioned above. You can get **EventDispatcher** first through **EventManager**, then call the specific internal interface, for example: ``` cs EventManager.GetDispatcher().AddListener(eventType, action, group, priorty, interrupt); @@ -304,8 +305,20 @@ EventManager.GetDispatcher().RemoveListener(eventType, action); *** -## 5. Compatibility Features -### 5.1. Compatibility List +## 5 Compatibility Features + +### 5.1 Performance Optimization +#### 5.1.1 Preloading +When a type is activated for the first time and registers for listening events, it is necessary to obtain all the methods of the type that need to be monitored and the attributes of the monitoring through reflection. The performance overhead due to reflection cannot be avoided, but it can be preloaded and cached. To reduce the overhead of instant use, so when necessary, you can actively call the following method at an appropriate time such as program startup or loading, and pre-register and cache the specified type of monitoring event information. +``` cs +public void PreRegister() +{ + var type = typeof(SomeClass); + EventListener.Register(type); +} +``` + +### 5.2 Compatibility List In order to be compatible with the existing event type definition methods in various projects, partial support for string / class / struct type events is provided, which can realize basic functions such as automatic/manual binding and event sending, but some functions will also be lost , See the function support list for details: |Function|Support| @@ -318,7 +331,7 @@ In order to be compatible with the existing event type definition methods in var |Listen group **ListenGroupAttribute**|√| |Listen event group type **ListenTypeAttribute**|×| -### 5.2. string Event +### 5.3 >string Event ``` cs // Define event type public static class StringEventDefine @@ -343,7 +356,7 @@ public void Receive(string message) } ``` -### 5.3. class / struct Event +### 5.4 class / struct Event ``` cs // Define event type public class ClassEventDefine diff --git a/.github/README_CN.md b/.github/README_CN.md index a86c64b..92b7458 100644 --- a/.github/README_CN.md +++ b/.github/README_CN.md @@ -14,62 +14,63 @@ > 官方交流QQ群:[1070645638](https://jq.qq.com/?_wv=1027&k=ezkLnUln) - -* 1. [简介](#) - * 1.1. [环境](#-1) - * 1.2. [文件夹](#-1) - * 1.3. [特性](#-1) - * 1.4. [结构](#-1) - * 1.5. [约定](#-1) - * 1.6. [接入](#-1) -* 2. [组件](#-1) - * 2.1. [事件管理器 EventManager](#EventManager) - * 2.2. [事件分发器 EventDispatcher](#EventDispatcher) - * 2.3. [事件监听器 EventListener](#EventListener) - * 2.4. [Object 事件监听器 ObjectListener](#ObjectObjectListener) - * 2.5. [Unity MonoBehaviour 事件监听器 MonoListener](#UnityMonoBehaviourMonoListener) - * 2.6. [监听事件处理器 EventHandler](#EventHandler) - * 2.6.1. [EventHandler](#EventHandler-1) - * 2.6.2. [EventHandler\](#EventHandlerT) -* 3. [可选特性标签 Attribute](#Attribute) - * 3.1. [事件定义枚举 EventEnumAttribute](#EventEnumAttribute) - * 3.2. [事件监听 ListenAttribute](#ListenAttribute) - * 3.3. [类型监听 ListenTypeAttribute](#ListenTypeAttribute) - * 3.4. [监听分组 ListenGroupAttribute](#ListenGroupAttribute) -* 4. [API](#API) - * 4.1. [事件定义](#-1) - * 4.2. [自动监听器](#-1) - * 4.3. [手动监听器](#-1) - * 4.4. [监听事件](#-1) - * 4.5. [监听类型](#-1) - * 4.6. [监听分组](#-1) - * 4.7. [手动注册/注销事件](#-1) - * 4.8. [发送事件](#-1) - * 4.9. [发送事件 (Unity线程安全)](#Unity) - * 4.10. [发送事件到对象](#-1) - * 4.11. [发送事件到分组](#-1) - * 4.12. [Full API](#FullAPI) -* 5. [兼容性功能](#-1) - * 5.1. [兼容性列表](#-1) - * 5.2. [string 类型事件](#string) - * 5.3. [class / struct 类型事件](#classstruct) - - - -## 1. 简介 -### 1.1. 环境 + + +- [UEvent](#uevent) + - [1 简介](#1-简介) + - [1.1 环境](#11-环境) + - [1.2 文件夹](#12-文件夹) + - [1.3 特性](#13-特性) + - [1.4 结构](#14-结构) + - [1.5 约定](#15-约定) + - [1.6 接入](#16-接入) + - [2 组件](#2-组件) + - [2.1 事件管理器 EventManager](#21-事件管理器-eventmanager) + - [2.2 事件分发器 EventDispatcher](#22-事件分发器-eventdispatcher) + - [2.3 事件监听器 EventListener](#23-事件监听器-eventlistener) + - [2.4 Object 事件监听器 ObjectListener](#24-object-事件监听器-objectlistener) + - [2.5 Unity MonoBehaviour 事件监听器 MonoListener](#25-unity-monobehaviour-事件监听器-monolistener) + - [2.6 监听事件处理器 EventHandler](#26-监听事件处理器-eventhandler) + - [2.6.1 EventHandler](#261-eventhandler) + - [2.6.2 EventHandler\](#262-eventhandlert) + - [3 可选特性标签 Attribute](#3-可选特性标签-attribute) + - [3.1 事件定义枚举 EventEnumAttribute](#31-事件定义枚举-eventenumattribute) + - [3.2 事件监听 ListenAttribute](#32-事件监听-listenattribute) + - [3.3 类型监听 ListenTypeAttribute](#33-类型监听-listentypeattribute) + - [3.4 监听分组 ListenGroupAttribute](#34-监听分组-listengroupattribute) + - [4 API](#4-api) + - [4.1 事件定义](#41-事件定义) + - [4.2 自动监听器](#42-自动监听器) + - [4.3 手动监听器](#43-手动监听器) + - [4.4 监听事件](#44-监听事件) + - [4.5 监听类型](#45-监听类型) + - [4.6 监听分组](#46-监听分组) + - [4.7 手动注册/注销事件](#47-手动注册注销事件) + - [4.8 发送事件](#48-发送事件) + - [4.9 发送事件 (Unity线程安全)](#49-发送事件-unity线程安全) + - [4.10 发送事件到对象](#410-发送事件到对象) + - [4.11 发送事件到分组](#411-发送事件到分组) + - [4.12 Full API](#412-full-api) + - [5 兼容性功能](#5-兼容性功能) + - [5.1 性能优化](#51-性能优化) + - [5.1.1 预加载](#511-预加载) + - [5.2 兼容性列表](#52-兼容性列表) + - [5.3 类型事件](#53--类型事件) + - [5.4 class / struct 类型事件](#54-class--struct-类型事件) + + + +## 1 简介 +### 1.1 环境 ![Unity: 2019.4.3f1](https://img.shields.io/badge/Unity-2017+-blue) ![.NET 4.x](https://img.shields.io/badge/.NET-4.x-blue) -### 1.2. 文件夹 +### 1.2 文件夹 * **Samples**: 例程文件夹,实际项目中可删除以减小空间占用。 * **CSharp**: 完全 .Net 实现的核心功能部分,可在 .Net 环境下独立使用。 * **Unity**: 依赖 UnityEngine 等 Unity 类库实现的额外功能,在 Unity 环境中工作时需要配合 Core 文件夹中的代码一起使用。 -### 1.3. 特性 +### 1.3 特性 * 支持通过枚举定义多组事件,按单一事件或者按事件类型进行监听。 * 同时支持 enum / string / class / struct 类型的事件定义最小化改动兼容不同项目。 * 支持监听接收事件优先级。 @@ -78,12 +79,12 @@ * 同时支持普通方法和委托形式的事件。 * 提供 `ObjectListener` 和 `MonoListener` 基类,使任何类获得自动注册/移除监听的特性,也可以自行实现 `IEventListener` 接口。 -### 1.4. 结构 +### 1.4 结构 * 事件管理器 **EventManager** -> 事件分发器 **EventDispatcher**-> 事件处理器 **EventHandler** * 事件监听器内部实现 **EventListener** -> 事件分发器 **EventDispatcher** * 事件监听器外部实现 **UserEventListener** -### 1.5. 约定 +### 1.5 约定 * 每一种类型的事件,使用一种枚举类型比如: AppEvent, GameEvent 等等,每种事件类型会对应一个 事件分发器 实例。 * 可以每个项目只使用一种事件类型,但不推荐。 * 方法型监听需要指定绑定对象,而委托型监听不需要指定对象。 @@ -93,30 +94,30 @@ * **enum** / **string** 类型事件使用 **UEvent** 接口,**class** / **struct** 类型事件使用 **UEvent\** 接口,接口没有做完整的类型约束,但请务必按照约定调用以避免不可预期的问题。 * 尽管同时支持多种类型的事件,但任然强烈建议在一个项目中只使用一种类型的事件格式。 -### 1.6. 接入 +### 1.6 接入 将 `Events` 文件夹整个放入 `UnityProject/Assets/Plugins/` 目录下即可。 *** -## 2. 组件 +## 2 组件 -### 2.1. 事件管理器 EventManager +### 2.1 事件管理器 EventManager 用于管理所有的事件分发器。 -### 2.2. 事件分发器 EventDispatcher +### 2.2 事件分发器 EventDispatcher 用于管理指定一种事件类型的监听注册/移除和事件分发。 -### 2.3. 事件监听器 EventListener +### 2.3 事件监听器 EventListener 用于管理指定一个对象的事件监听注册/反注册。 -### 2.4. Object 事件监听器 ObjectListener +### 2.4 Object 事件监听器 ObjectListener 普通类型通过继承该类或者使用自身初始化该类来实现事件机制,可以对该对象自动进行注册、反注册,同时提供快捷调用的监听注册、移除、事件分发接口。 -### 2.5. Unity MonoBehaviour 事件监听器 MonoListener +### 2.5 Unity MonoBehaviour 事件监听器 MonoListener 与 ObjectListener 接口相同,提供给 MonoBehaviour 游戏对象使用。 -### 2.6. 监听事件处理器 EventHandler -#### 2.6.1. EventHandler +### 2.6 监听事件处理器 EventHandler +#### 2.6.1 EventHandler |属性|描述|备注| |-|-|-| |Type|事件定义类型|事件定义 `enum/string/class/struct` 等对象的 Type,相当于 `typeof(X)`| @@ -129,7 +130,7 @@ |Parameters|监听方法的参数|| |Action|监听委托 Action|| -#### 2.6.2. EventHandler\ +#### 2.6.2 EventHandler\ |属性|描述|备注| |-|-|-| |ActionT|监听委托 Action\|| @@ -138,11 +139,11 @@ *** -## 3. 可选特性标签 Attribute +## 3 可选特性标签 Attribute -### 3.1. 事件定义枚举 EventEnumAttribute +### 3.1 事件定义枚举 EventEnumAttribute 该特性标签为预留功能,后期可能用于反射自动获取分散于不同程序集中的事件定义,目前暂无功能。 -### 3.2. 事件监听 ListenAttribute +### 3.2 事件监听 ListenAttribute 用于标记该类型内需要监听指定事件的方法。 事件监听器会自动搜索所有包含该特性的方法,进行监听注册。 * **属性** @@ -155,14 +156,14 @@ * 必须是实例对象 * 必须是非静态方法 -### 3.3. 类型监听 ListenTypeAttribute +### 3.3 类型监听 ListenTypeAttribute 加上该标记的方法能够接收指定事件类型的所有事件,会遍历所有枚举并注册所有监听 * **属性** * **Type** : 事件枚举类型 * **Priority** : 优先级 * **Interrupt** : 是否中断事件队列 -### 3.4. 监听分组 ListenGroupAttribute +### 3.4 监听分组 ListenGroupAttribute 只有通过 `DispatchGroup` 接口发送的事件,与该特性标签中的分组对应时才会触发事件。 * **属性** * **Type** : 事件类型 @@ -175,9 +176,9 @@ *** -## 4. API +## 4 API -### 4.1. 事件定义 +### 4.1 事件定义 ``` cs /* UEvent 推荐使用枚举类型定义事件,通过不同的枚举实现事件分组功能。 @@ -193,7 +194,7 @@ public enum GameEventType } ``` -### 4.2. 自动监听器 +### 4.2 自动监听器 ``` cs // 任意 C# 类获得监听能力 public class TestClass : EventListener @@ -206,7 +207,7 @@ public class UnityTestClass : MonoEventListener } ``` -### 4.3. 手动监听器 +### 4.3 手动监听器 ``` cs // 生成指定对象的监听器,一般对象生成时执行 var listener = new EventListener(this); @@ -218,7 +219,7 @@ EventListener.Register(); EventListener.DeRegister(); ``` -### 4.4. 监听事件 +### 4.4 监听事件 ``` cs // 监听单个事件,无优先级 [Listen(GameEvent.GameStart)] @@ -239,7 +240,7 @@ public void TestMethod() } ``` -### 4.5. 监听类型 +### 4.5 监听类型 ``` cs [ListenType(typeof(GameEvent))] public void TestMethod() @@ -247,7 +248,7 @@ public void TestMethod() } ``` -### 4.6. 监听分组 +### 4.6 监听分组 ``` cs [ListenGroup(GameEvent.GameStart, "Player")] public void TestMethod() @@ -255,7 +256,7 @@ public void TestMethod() } ``` -### 4.7. 手动注册/注销事件 +### 4.7 手动注册/注销事件 ``` cs // 添加监听 UEvent.Listen(eventType, this, methodInfo, group, priorty, interrupt); @@ -273,29 +274,29 @@ UEvent.Remove(eventType, this, method); UEvent.Remove(eventType, action); ``` -### 4.8. 发送事件 +### 4.8 发送事件 ``` cs UEvent.Dispatch(eventType, args); ``` -### 4.9. 发送事件 (Unity线程安全) +### 4.9 发送事件 (Unity线程安全) ``` cs // 该接口会将事件以委托形式转交给Unity主线程执行,仅Unity扩展中可用。 UEvent.DispatchSafe(eventType, args); ``` -### 4.10. 发送事件到对象 +### 4.10 发送事件到对象 ``` cs UEvent.DispatchTo(eventType, target, args); ``` -### 4.11. 发送事件到分组 +### 4.11 发送事件到分组 ``` cs // `Group` 参数如果为空,则等效为调用 `Dispatch` 接口,事件将发送给任何没有分组的监听方法。 UEvent.DispatchGroup(eventType, group, args); ``` -### 4.12. Full API +### 4.12 Full API 如果想获得 **UEvent** 的完整功能或调用内部接口,则可以通过使用以下方式访问调用,接口与上文提到的快速调用接口略有差异,通过 **EventManager** 先获取到对应事件的 **EventDispatcher**,再调用具体内部接口,例如: ``` cs EventManager.GetDispatcher().AddListener(eventType, action, group, priorty, interrupt); @@ -305,8 +306,19 @@ EventManager.GetDispatcher().RemoveListener(eventType, action); *** -## 5. 兼容性功能 -### 5.1. 兼容性列表 +## 5 兼容性功能 +### 5.1 性能优化 +#### 5.1.1 预加载 +当某个类型被第一次激活并注册监听事件时,需要通过反射获取该类型所有需要被监听的方法以及监听的规则特性,由于反射的性能开销无法被避免,但可以通过预先加载和缓存机制来减少即时使用时的开销,因此必要的时候,可以在程序启动或者加载等合适的时机,主动调用以下方法,预先注册缓存指定类型的监听事件信息。 +``` cs +public void PreRegister() +{ + var type = typeof(SomeClass); + EventListener.Register(type); +} +``` + +### 5.2 兼容性列表 为了兼容各种项目中已有的事件类型定义方式,提供了对 string / class / struct 类型事件的部分支持,可以实现事件的自动/手动绑定和事件发送等基本功能,但也会失去部分功能,详见功能支持列表: |功能|支持| @@ -319,7 +331,7 @@ EventManager.GetDispatcher().RemoveListener(eventType, action); |监听分组 **ListenGroupAttribute**|√| |监听同类型事件 **ListenTypeAttribute**|×| -### 5.2. string 类型事件 +### 5.3 类型事件 ``` cs // 定义 public static class StringEventDefine @@ -344,7 +356,7 @@ public void Receive(string message) } ``` -### 5.3. class / struct 类型事件 +### 5.4 class / struct 类型事件 ``` cs // 定义 public class ClassEventDefine diff --git a/CSharp/Script/Attribute/Base.meta b/CSharp/Script/Attribute/Base.meta new file mode 100644 index 0000000..6b6c66f --- /dev/null +++ b/CSharp/Script/Attribute/Base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c76413a0fdb6dd44ba26bcf3c0f51168 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/CSharp/Script/Attribute/Base/EventAttributeBase.cs b/CSharp/Script/Attribute/Base/EventAttributeBase.cs new file mode 100644 index 0000000..6538176 --- /dev/null +++ b/CSharp/Script/Attribute/Base/EventAttributeBase.cs @@ -0,0 +1,17 @@ +///////////////////////////////////////////////////////////////////////////// +// +// Script : EventAttributeBase.cs +// Info : 事件特性基类 +// Author : ls9512 +// E-mail : ls9512@vip.qq.com +// +///////////////////////////////////////////////////////////////////////////// +using System; + +namespace Aya.Events +{ + public abstract class EventAttributeBase : Attribute + { + + } +} \ No newline at end of file diff --git a/CSharp/Script/Attribute/Base/EventAttributeBase.cs.meta b/CSharp/Script/Attribute/Base/EventAttributeBase.cs.meta new file mode 100644 index 0000000..f231cc8 --- /dev/null +++ b/CSharp/Script/Attribute/Base/EventAttributeBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3586ea81fa393f149a7c459447fc69a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/CSharp/Script/Attribute/EventEnumAttribute.cs b/CSharp/Script/Attribute/EventEnumAttribute.cs index 167cac7..077981a 100644 --- a/CSharp/Script/Attribute/EventEnumAttribute.cs +++ b/CSharp/Script/Attribute/EventEnumAttribute.cs @@ -11,7 +11,7 @@ namespace Aya.Events { [AttributeUsage(AttributeTargets.Enum, AllowMultiple = false)] - public class EventEnumAttribute : Attribute + public class EventEnumAttribute : EventAttributeBase { } } diff --git a/CSharp/Script/Attribute/ListenAttribute.cs b/CSharp/Script/Attribute/ListenAttribute.cs index ba1e52f..3127f3a 100644 --- a/CSharp/Script/Attribute/ListenAttribute.cs +++ b/CSharp/Script/Attribute/ListenAttribute.cs @@ -11,22 +11,22 @@ namespace Aya.Events { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class ListenAttribute : Attribute + public class ListenAttribute : EventAttributeBase { /// /// 事件类型 /// - public object[] Types { get; } + public object[] Types; /// /// 优先级 /// - public int Priority { get; } + public int Priority; /// /// 是否中断事件队列 /// - public bool Interrupt { get; } + public bool Interrupt; /// /// 监听事件 diff --git a/CSharp/Script/Attribute/ListenGroupAttribute.cs b/CSharp/Script/Attribute/ListenGroupAttribute.cs index 1ddcbd1..44329b0 100644 --- a/CSharp/Script/Attribute/ListenGroupAttribute.cs +++ b/CSharp/Script/Attribute/ListenGroupAttribute.cs @@ -11,27 +11,27 @@ namespace Aya.Events { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class ListenGroupAttribute : Attribute + public class ListenGroupAttribute : EventAttributeBase { /// /// 事件类型 /// - public object Type { get; } + public object Type; /// /// 事件分组 /// - public object Group { get; } + public object Group; /// /// 优先级 /// - public int Priority { get; } + public int Priority; /// /// 是否中断事件队列 /// - public bool Interrupt { get; } + public bool Interrupt; /// /// 监听所有事件 diff --git a/CSharp/Script/Attribute/ListenTypeAttribute.cs b/CSharp/Script/Attribute/ListenTypeAttribute.cs index 9e793cb..8541af7 100644 --- a/CSharp/Script/Attribute/ListenTypeAttribute.cs +++ b/CSharp/Script/Attribute/ListenTypeAttribute.cs @@ -11,7 +11,7 @@ namespace Aya.Events { [AttributeUsage(AttributeTargets.Method)] - public class ListenTypeAttribute : Attribute + public class ListenTypeAttribute : EventAttributeBase { /// /// 监听事件枚举类型 @@ -21,12 +21,12 @@ public class ListenTypeAttribute : Attribute /// /// 优先级 /// - public int Priority { get; } + public int Priority; /// /// 是否中断事件队列 /// - public bool Interrupt { get; } + public bool Interrupt; /// /// 监听所有事件 diff --git a/CSharp/Script/EventListener.cs b/CSharp/Script/EventListener.cs index 88c6960..36186b3 100644 --- a/CSharp/Script/EventListener.cs +++ b/CSharp/Script/EventListener.cs @@ -19,7 +19,7 @@ public partial class EventListener /// /// 监听对象类型 - 监听方法 - 包含监听事件类型列表 /// - protected static Dictionary>> MethodMap = new Dictionary>>(); + protected static Dictionary>> MethodMap = new Dictionary>>(); /// /// 事件监听对象 @@ -44,55 +44,58 @@ public EventListener(object listener) #region Register / DeRegister - /// - /// 注册监听器 - /// - public void Register() + public static void Register(Type objType) { - var objType = Listener.GetType(); - // 如果该类型对象已经被注册过,则直接遍历该类型所有需要监听的方法并注册到事件分发器 - if (MethodMap.ContainsKey(objType)) - { - var tempObjEventDic = MethodMap[objType]; - foreach (var kv in tempObjEventDic) - { - var method = kv.Key; - var eventAttributeList = kv.Value; - for (var i = 0; i < eventAttributeList.Count; i++) - { - var eventAttribute = eventAttributeList[i]; - _addListenerWithAttribute(eventAttribute, method); - } - } - - return; - } - // 如果是未注册过的对象类型,则遍历所有被标记需要监听的方法,进行注册 - var objEventDic = new Dictionary>(); + if (MethodMap.TryGetValue(objType, out var _)) return; + var objEventDic = new Dictionary>(); MethodMap.Add(objType, objEventDic); var methodInfos = objType.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); for (var i = 0; i < methodInfos.Length; i++) { var methodInfo = methodInfos[i]; - var attributes = methodInfo.GetCustomAttributes(typeof(Attribute), false); + var attributes = methodInfo.GetCustomAttributes(typeof(EventAttributeBase), false); if (attributes.Length <= 0) continue; - var eventAttributeList = new List(); + var eventAttributeList = new List(); objEventDic.Add(methodInfo, eventAttributeList); for (var j = 0; j < attributes.Length; j++) { var attribute = attributes[j]; if (attribute == null) return; - var attributeTemp = attribute as Attribute; + var attributeTemp = attribute as EventAttributeBase; if (attributeTemp == null) return; - _addListenerWithAttribute(attributeTemp, methodInfo); eventAttributeList.Add(attributeTemp); } } } + /// + /// 注册监听器 + /// + public void Register() + { + var objType = Listener.GetType(); + // 如果该类型对象已经被注册过,则直接遍历该类型所有需要监听的方法并注册到事件分发器 + if (!MethodMap.TryGetValue(objType, out var tempObjEventDic)) + { + Register(objType); + tempObjEventDic = MethodMap[objType]; + } + + foreach (var kv in tempObjEventDic) + { + var method = kv.Key; + var eventAttributeList = kv.Value; + for (var i = 0; i < eventAttributeList.Count; i++) + { + var eventAttribute = eventAttributeList[i]; + _addListenerWithAttribute(eventAttribute, method); + } + } + } + /// /// 反注册监听器 /// @@ -124,7 +127,7 @@ public void UpdateRegister() /// /// 特性 /// 监听方法 - private void _addListenerWithAttribute(Attribute attribute, MethodInfo methodInfo) + private void _addListenerWithAttribute(EventAttributeBase attribute, MethodInfo methodInfo) { // Listen Attribute if (attribute is ListenAttribute attrListen) @@ -182,10 +185,7 @@ private void _addListener(object eventType, MethodInfo methodInfo, object group } dispatcher.AddListener(eventType, Listener, methodInfo, group, priority, interrupt); - if (!RegisteredDispatchers.Contains(dispatcher)) - { - RegisteredDispatchers.Add(dispatcher); - } + RegisteredDispatchers.Add(dispatcher); } #endregion diff --git a/package.json b/package.json index 63e3748..849241d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "com.ls9512.uevent", "displayName": "UEvent", "description": "UEvent is a general message event component that can be used in Unity and .Net environment.", - "version": "1.0.6", + "version": "20230726", "unity": "2017.1", "license": "MIT", "repository": {