个人使用的事件管理者,用于项目中的事件分发,以增加代码的灵活性。
事件
由于本人习惯,本着“多一事不如少一事“”的原则,使用的是程序库中自带的事件EventHandler:
using System.Runtime.InteropServices;
namespace System
{
[ComVisible(true)]
public delegate void EventHandler(object sender, EventArgs e);
}
其中,参数EventArgs类,也是程序库中自带的:
using System.Runtime.InteropServices;
namespace System
{
[ComVisible(true)]
public class EventArgs
{
public static readonly EventArgs Empty;
public EventArgs();
}
}
管理者
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 事件管理者
/// </summary>
public class EventManager : BaseManager<EventManager>
{
Dictionary<GameObject, Dictionary<Type, EventHandler>> m_dic = new Dictionary<GameObject, Dictionary<Type, EventHandler>>();
/// <summary>
/// 增加事件
/// </summary>
/// <typeparam name="T">事件的参数类</typeparam>
/// <param name="owner">拥有对象</param>
/// <param name="eh">事件</param>
public void AddEvent<T>(GameObject owner, EventHandler eh) where T : EventArgs
{
if (!m_dic.ContainsKey(owner))
{
m_dic[owner] = new Dictionary<Type, EventHandler>();
}
Type type = typeof(T);
if (m_dic[owner].ContainsKey(type))
{
m_dic[owner][type] += eh;
}
else
{
m_dic[owner][type] = eh;
}
}
/// <summary>
/// 触发事件
/// </summary>
/// <typeparam name="T">事件的参数类</typeparam>
/// <param name="owner">拥有对象</param>
/// <param name="sender">事件的参数</param>
/// <param name="t">事件的参数</param>
public void TriggerEvent<T>(GameObject owner, object sender, T t) where T : EventArgs
{
if (m_dic.ContainsKey(owner))
{
Type type = typeof(T);
if (m_dic[owner].ContainsKey(type))
{
m_dic[owner][type].Invoke(sender, t);
}
}
}
/// <summary>
/// 移除事件
/// </summary>
/// <typeparam name="T">事件的参数类</typeparam>
/// <param name="owner">拥有对象</param>
/// <param name="eh">事件</param>
public void RemoveEvent<T>(GameObject owner, EventHandler eh) where T : EventArgs
{
if (m_dic.ContainsKey(owner))
{
Type type = typeof(T);
if (m_dic[owner].ContainsKey(type))
{
m_dic[owner][type] -= eh;
}
}
}
}
该类为单例,继承的便是我自己编写的一个单例父类,之前有篇专门记录的文章:可点击查看相关文章。
在代码中,有一个两重字典,用于准确确定到我们所要用到的事件。第一重为GameObject类型,是场景中的一个物体;第二重为一个衍生自EventArgs类型的类的类型。
使用
使用这个事件管理者时,先写一个与事件EventHandler结构一样的一个函数:
public void TestEvent(object sender, EventArgs e)
{
}
然后再创建一个衍生自EventArgs类型的类:
public class TestEventArgs : EventArgs
{
}
然后将函数中所要真正用到的参数,以字段的形式创建于该类中。再只需要在函数中,将EventArgs类的参数转换成对应类型(如例:TestEventArgs)
public void TestEvent(object sender, EventArgs e)
{
TestEventArgs tea=(TestEventArgs)e;
}
便可以获取到真正传入的所需要的参数了。在其之后便可编写执行逻辑。
使用事件前先将其添加入事件管理者:
EventManager.GetInstance().AddEvent<TestEventArgs>(gameObject, TestEvent);
触发事件时:
EventManager.GetInstance().TriggerEvent(gameObject, 0, new TestEventArgs());
其中的数字0,便是函数的第1个object类型的参数,如有需要,可自行更改。
最后不需要其事件时,可以将其在管理者中删除:
EventManager.GetInstance().RemoveEvent<TestEventArgs>(gameObject, TestEvent);