好处
- 不用手动添加订阅
- 代码跟容易管理
缺点
- 不能取消订阅
使用
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
EventSystem.Instance.Push(new KillPlayer() {
Player1="坤坤",
Player2= "I坤的真爱粉"
});
}
}
public struct KillPlayer
{
public string Player1;
public string Player2;
}
[Event]
public class KillPlayer_UpdateUI : XEvent<KillPlayer>
{
protected override void Run(KillPlayer t)
{
Debug.Log($"KillPlayer_UpdateUI:{t.Player1}击杀了{t.Player2}");
}
}
[Event]
public class KillPlayer_LogInfo : XEvent<KillPlayer>
{
protected override void Run(KillPlayer t)
{
Debug.Log($"KillPlayer_LogInfo:{t.Player1}击杀了{t.Player2}");
}
}
源码
using QFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;
public interface IEvent
{
Type Type { get; }
}
public abstract class XEvent<T>:IEvent where T:struct
{
public Type Type
{
get
{
return typeof(T);
}
}
protected abstract void Run( T t);
public void Handle(T t)
{
try
{
Run(t);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
[AttributeUsage(AttributeTargets.Class)]
public class BaseAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class EventAttribute : BaseAttribute
{
}
public class EventSystem
{
private static EventSystem instance;
public static EventSystem Instance { get {
if(instance==null)
instance = new EventSystem();
return instance;
} }
private EventSystem()
{
OnSingletonInit();
}
Dictionary<Type, List<IEvent>> EventPool = new Dictionary<Type, List<IEvent>>();
public void OnSingletonInit()
{
UnOrderMultiMapSet<Type, Type> types = new UnOrderMultiMapSet<Type, Type>();
Dictionary<string, Type> types1 = AssemblyHelper.GetAssemblyTypes(Assembly.GetAssembly(typeof(EventSystem)));
foreach ((string fullName, Type type) in types1)
{
if (type.IsAbstract)
{
continue;
}
// 记录所有的有BaseAttribute标记的的类型
object[] objects = type.GetCustomAttributes(typeof(BaseAttribute), true);
foreach (object o in objects)
{
types.Add(o.GetType(), type);
}
}
HashSet<Type> hs=types[typeof(EventAttribute)];
foreach (var v in hs)
{
EventAttribute attr = v.GetCustomAttributes(typeof(EventAttribute), false)[0] as EventAttribute;
var interfaces = v.GetInterfaces();
if (interfaces.Contains(typeof(IEvent)))
{
var value = Activator.CreateInstance(v) as IEvent;
var key = value.Type;
if (!EventPool.ContainsKey(key))
{
EventPool.Add(key, new List<IEvent>());
}
EventPool[key].Add(value);
}
}
}
public void Push<T>(T t) where T : struct
{
Type type= typeof(T);
if (EventPool.ContainsKey(type))
{
foreach (var v in EventPool[type])
{
XEvent<T> xEvent =v as XEvent<T>;
xEvent.Handle(t);
}
}
}
}
public static class AssemblyHelper
{
public static Dictionary<string, Type> GetAssemblyTypes(params Assembly[] args)
{
Dictionary<string, Type> types = new Dictionary<string, Type>();
foreach (Assembly ass in args)
{
foreach (Type type in ass.GetTypes())
{
types[type.FullName] = type;
}
}
return types;
}
}
public class UnOrderMultiMapSet<T, K> : Dictionary<T, HashSet<K>>
{
// 重用HashSet
public new HashSet<K> this[T t]
{
get
{
HashSet<K> set;
if (!this.TryGetValue(t, out set))
{
set = new HashSet<K>();
}
return set;
}
}
public Dictionary<T, HashSet<K>> GetDictionary()
{
return this;
}
public void Add(T t, K k)
{
HashSet<K> set;
this.TryGetValue(t, out set);
if (set == null)
{
set = new HashSet<K>();
base[t] = set;
}
set.Add(k);
}
public bool Remove(T t, K k)
{
HashSet<K> set;
this.TryGetValue(t, out set);
if (set == null)
{
return false;
}
if (!set.Remove(k))
{
return false;
}
if (set.Count == 0)
{
this.Remove(t);
}
return true;
}
public bool Contains(T t, K k)
{
HashSet<K> set;
this.TryGetValue(t, out set);
if (set == null)
{
return false;
}
return set.Contains(k);
}
public new int Count
{
get
{
int count = 0;
foreach (KeyValuePair<T, HashSet<K>> kv in this)
{
count += kv.Value.Count;
}
return count;
}
}
}
https://github.com/egametang/ET