委托
基础概念
委托(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);
}
}
输出: