CenterBase
Coding Style wiki
CenterBase<TCenter, TClass> 是 CenterFrame 的中心註冊抽象基類,內建執行緒安全單例與 Dictionary<int, TClass> 型別安全快取,統一提供**註冊(Add)、移除(Delete)、查找(Find)**等物件管理介面。APICenter(APIBase)與 EventCenter(EventBase)皆以此為共同基底,也可自訂 TClass 基底型別實作自己的中心。
| 命名空間 | OxGFrame.CenterFrame |
| 類型 | public abstract class |
| 原始碼 | CenterBase.cs |
using OxGFrame.CenterFrame;
宣告
public abstract class CenterBase<TCenter, TClass> where TCenter : CenterBase<TCenter, TClass>, new()
泛型參數
| 泛型參數 | 說明 |
|---|---|
| TCenter | 中心子類自身型別(CRTP 自我參照約束),需具備無參數建構子(new())。 |
| TClass | 受管理物件的基底型別(如 APICenter 的 APIBase、EventCenter 的 EventBase)。 |
繼承時將子類自身與受管理的基底型別作為泛型參數傳入:
public class APICenterExample : CenterBase<APICenterExample, APIBase> { /* ... */ }
public class EventCenterExample : CenterBase<EventCenterExample, EventBase> { /* ... */ }
運作方式
單例與註冊時機
CenterBase<TCenter, TClass> 內建執行緒安全的延遲單例(Double-Checked Locking)。首次呼叫任一 Default API 靜態方法時,自動建立 TCenter 實例並執行其建構子;建議於子類建構子中以 Register 完成物件註冊。
重要 不可於子類建構子中呼叫任何 Default API 靜態方法(如 Add / Find),會導致 GetInstance() 遞迴而 StackOverflow(死循環);建構子中請改用實例成員方法(如 Register)。
ID 規則
- 每個註冊物件以唯一的
intid 作為快取鍵。泛型多載未指定 id 時,以typeof(UClass).GetHashCode()作為 id(同型別僅能註冊一個實例)。 - 指定 id 的多載可自訂 id,同型別即可註冊多個實例。
- 相同 id 重複註冊會輸出警告日誌並略過,不會覆蓋既有物件。
Default API 與成員方法
靜態 Default API(Add / Delete / Find)內部皆透過單例轉呼叫對應的實例成員方法(Register / Remove / Get):
- 外部呼叫端:直接以子類類名使用 Default API(如
EventCenterExample.Find<UClass>())。 - 子類內部(建構子):使用實例成員方法(如
this.Register<UClass>())。
注意 CenterBase 僅負責物件的註冊與快取管理;若受管理物件持有 Unity 資源(如 Prefab),請於移除前自行配合 AssetLoaders 進行正確的釋放處理。
繼承實作範例
以 EventCenter 風格為例,自訂事件中心與事件類:
using Cysharp.Threading.Tasks;
using OxGFrame.CenterFrame;
using OxGFrame.CenterFrame.EventCenter;
using UnityEngine;
// 自訂事件中心:TCenter 傳入 子類自身(CRTP),TClass 指定受管理的基底型別
public class EventCenterExample : CenterBase<EventCenterExample, EventBase>
{
public EventCenterExample()
{
// 建構子中註冊事件(僅能使用 實例成員方法 Register,不可呼叫 Default API)
this.Register<EventMsgTest>();
}
}
// 自訂事件:繼承 EventBase
public class EventMsgTest : EventBase
{
private string _message;
public void Emit(string message)
{
this._message = message;
this.HandleEvent().Forget();
}
public async override UniTaskVoid HandleEvent()
{
// 處理事件內容
Debug.Log($"Received message: {this._message}");
this.Release();
}
protected override void Release()
{
// 釋放事件持有的資料
this._message = null;
}
}
呼叫端透過 Default API 查找並派送事件:
// 以型別查找已註冊的事件並派送
EventCenterExample.Find<EventMsgTest>()?.Emit("Hello OxGFrame");
APICenter 風格作法相同,僅將 TClass 改為 APIBase:
using OxGFrame.CenterFrame;
using OxGFrame.CenterFrame.APICenter;
// APIGetPlayerData 為繼承 APIBase 的自訂 API 類
public class APICenterExample : CenterBase<APICenterExample, APIBase>
{
public APICenterExample()
{
this.Register<APIGetPlayerData>();
}
}
提醒 可透過 Project 視窗右鍵範本快速建立:Create → OxGFrame → Center Frame → Event Center / API Center → Template Scripts 下的範本腳本。
成員總覽
靜態方法(Default API)
繼承後直接以子類類名呼叫(如 EventCenterExample.Find<UClass>())。
| 方法 | 說明 |
|---|---|
| Add | 實例化並註冊物件至快取。 |
| Delete | 從快取移除物件。 |
| DeleteAll | 清空快取中的所有物件。 |
| Find<UClass> | 從快取查找物件並轉型回傳。 |
一般方法(實例成員)
| 方法 | 說明 |
|---|---|
| Get<UClass> | 從快取取得物件並轉型(Find 的成員版本)。 |
| Has<UClass> | 檢查物件是否已註冊。 |
| Register | 註冊物件至快取(Add 的成員版本)。 |
| Remove | 從快取移除物件(Delete 的成員版本)。 |
| RemoveAll | 清空快取(DeleteAll 的成員版本)。 |
受保護成員(繼承後可用)
| 成員 | 型別 | 說明 |
|---|---|---|
GetInstance() | static TCenter | 取得中心單例(延遲建立、執行緒安全)。 |
GetFromCache(int id) | TClass | 從快取取出物件;查無時輸出錯誤日誌並回傳 default。 |
HasInCache(int id) | bool | 檢查快取中是否存在指定 id。 |
Add
public static void Add<UClass>() where UClass : TClass, new()
public static void Add<UClass>(int id) where UClass : TClass, new()
public static void Add(int id, TClass @class)
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 作為 id。 |
| @class | TClass | 已建立的物件實例(以指定 id 註冊)。 |
說明
實例化(new UClass())並註冊物件至快取,或以指定 id 直接註冊既有實例。
- 泛型多載要求
UClass具備無參數建構子(new()約束)。 - 相同 id 重複註冊會輸出警告並略過,不會覆蓋既有物件。
範例
// 以型別 hash 作為 id 註冊
EventCenterExample.Add<EventMsgTest>();
// 以自訂 id 註冊既有實例
EventCenterExample.Add(0x01, new EventMsgTest());
Delete
public static void Delete<UClass>() where UClass : TClass
public static void Delete(int id)
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 查找。 |
說明
從快取移除已註冊的物件;查無時不動作。
DeleteAll
public static void DeleteAll()
說明
清空快取中的所有已註冊物件。
Find<UClass>
public static UClass Find<UClass>() where UClass : TClass
public static UClass Find<UClass>(int id) where UClass : TClass
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 查找。 |
回傳值
UClass — 快取中對應的物件(已轉型為 UClass);查無時輸出錯誤日誌並回傳 default(參考型別即 null)。
說明
從快取查找已註冊的物件並自 動轉型。無參數多載以型別 hash 查找,僅適用於未指定 id 註冊的物件;以自訂 id 註冊者請使用 Find<UClass>(int id)。
範例
var evt = EventCenterExample.Find<EventMsgTest>();
evt?.Emit("Hello OxGFrame");
Get<UClass>
public UClass Get<UClass>() where UClass : TClass
public UClass Get<UClass>(int eventId) where UClass : TClass
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| eventId | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 查找。 |
回傳值
UClass — 快取中對應的物件(已轉型為 UClass);查無時輸出錯誤日誌並回傳 default。
說明
Find<UClass> 的實例成員版本,供子類內部使用。
Has<UClass>
public bool Has<UClass>() where UClass : TClass
public bool Has<UClass>(int id) where UClass : TClass
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 檢查。 |
回傳值
bool — 指定物件是否已註冊於快取。
說明
檢查物件是否已註冊。可於註冊或查找前先行判斷,避免重複註冊的警告或查無的錯誤日誌。
Register
public void Register<UClass>() where UClass : TClass, new()
public void Register<UClass>(int id) where UClass : TClass, new()
public void Register(int id, TClass @class)
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 作為 id。 |
| @class | TClass | 已建立的物件實例(以指定 id 註冊)。 |
說明
Add 的實例成員版本,於子類建構子中註冊物件時使用(建構子中不可呼叫靜態 Default API)。相同 id 重複註冊會輸出警告並略過。
範例
public EventCenterExample()
{
this.Register<EventMsgTest>();
}
Remove
public void Remove<UClass>() where UClass : TClass
public void Remove(int id)
參數
| 參數 | 型別 | 說明 |
|---|---|---|
| id | int | 註冊 id。未指定時,以 typeof(UClass).GetHashCode() 查找。 |
說明
Delete 的實例成員版本;查無時不動作。
RemoveAll
public void RemoveAll()
說明
DeleteAll 的實例成員版本,清空快取中的所有已註冊物件。