委托

基础概念

委托(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);
    }
}

输出:

posted @ 2024-10-18 11:28  请明月  阅读(4)  评论(0编辑  收藏  举报