基礎概念
委託(Delegate)特別用於實現事件和回撥方法。所有的委託(Delegate)都派生自 System.Delegate 類。
C# 事件(Event)是一種成員,用於將特定的事件通知傳送給訂閱者。事件通常用於實現觀察者模式,它允許一個物件將狀態的變化通知其他物件,而不需要知道這些物件的細節。
事件可以搭配委託做到觸發和回撥
例項化委託的格式:
//delegate <return type> <delegate-name> <parameter list>
public delegate void printString(string s);
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
委託的多播
委託物件可使用 "+" 運算子進行合併。一個合併委託呼叫它所合併的兩個委託。只有相同型別的委託可被合併。"-" 運算子可用於從合併的委託中移除元件委託。
public delegate void printString(string s);
//WriteToScreen與WriteToFile是具體方法
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
printString ps +=ps1;
printString ps +=ps2;
ps("輸入string值");//此時ps就會同時執行ps1和ps2
將委託作為引數回撥也是運用的一個方面
public delegate void printString(string s);
//WriteToScreen是具體方法
printString ps1 = new printString(WriteToScreen);
public static void sendString(printString ps){
ps("輸入一個string值");
}
sendString(ps1);//執行ps1中的方法
程式碼示例
以下示例完成了一個簡單的委託中心,因為這裡沒有使用Event(事件),所以這裡沒有設定回撥。
DelegateCenter.cs
using System;
using System.Collections.Generic;
using UnityEngine;
public class DelegateCenter
{
#region 單例
private static DelegateCenter _instance;
public static DelegateCenter Instance
{
get
{
if(_instance == null)
{
_instance = new DelegateCenter();
}
return _instance;
}
}
#endregion
public delegate void DelegateEvent();
private Dictionary<string, DelegateEvent> _events = new Dictionary<string, DelegateEvent>();
public void RigisterDelegateEvent(string delegateName, DelegateEvent de)
{
if (_events.ContainsKey(delegateName))
{
_events[delegateName] += de;
}
else
{
_events.Add(delegateName, de);
}
Debug.Log($"{delegateName}事件註冊成功!");
}
public void InvokeDelegateEvent(string delegateName)
{
if (_events.ContainsKey(delegateName))
{
_events[delegateName].Invoke();
}
}
public void RemoveDelegateEvent(string delegateName, DelegateEvent de)
{
if (_events.ContainsKey(delegateName))
{
_events[delegateName] -= de;
Debug.Log($"{delegateName}事件解除安裝成功!");
}
}
public void RemoveAllDelegateEvent()
{
_events.Clear();
Debug.Log($"所有事件解除安裝成功!");
}
}
表現
這裡的表現是使用上面的委託中心,因為這裡掛載了MonoBehaviour所以使用了幾個它的生命週期函式,在按下ASD鍵時會觸發相應的事件,但掛載了這個指令碼的物件刪除時會清除註冊了的事件。
using System;
using UnityEngine;
public class delegateTest:MonoBehaviour
{
private void Start()
{
DelegateCenter.Instance.RigisterDelegateEvent("GameStart", GameStart);
DelegateCenter.Instance.RigisterDelegateEvent("ResourcesLoad", ResourcesLoad);
DelegateCenter.Instance.RigisterDelegateEvent("XluaHotFix", XluaHotFix);
}
private void Update()
{
if (Input.GetKeyUp(KeyCode.A))
{
DelegateCenter.Instance.InvokeDelegateEvent("GameStart");
}
else if (Input.GetKeyUp(KeyCode.S))
{
DelegateCenter.Instance.InvokeDelegateEvent("ResourcesLoad");
}
else if (Input.GetKeyUp(KeyCode.D))
{
DelegateCenter.Instance.InvokeDelegateEvent("ResourcesLoad");
}
}
public void GameStart()
{
Debug.Log("遊戲開始");
}
public void ResourcesLoad()
{
Debug.Log("讀取資源");
}
public void XluaHotFix()
{
Debug.Log("開始熱更新");
}
private void OnDestory()
{
DelegateCenter.Instance.RemoveDelegateEvent("GameStart", GameStart);
DelegateCenter.Instance.RemoveDelegateEvent("ResourcesLoad", ResourcesLoad);
DelegateCenter.Instance.RemoveDelegateEvent("XluaHotFix", XluaHotFix);
}
}
輸出: