// Copyright (c) 2025 EFramework Innovation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
using System;
using System.Collections.Generic;
using System.Reflection;
using EFramework.Unity.Utility;
namespace EFramework.Unity.MVVM
{
///
/// XModule 提供了业务开发的基础模块,支持模块的生命周期管理和事件系统集成。
///
///
///
/// 功能特性
/// - 生命周期管理:提供 Awake、Start、Reset、Stop 状态控制
/// - 事件系统集成:通过事件系统对模块与视图间的交互进行解耦合
///
/// 使用手册
/// 1. 定义模块
///
/// // 基础模块
/// public class MyModule : XModule.Base
/// {
/// public override string Name => "MyModule";
/// }
///
/// // 单例模块
/// public class MySingletonModule : XModule.Base<MySingletonModule>
/// {
/// public override string Name => "MySingletonModule";
/// }
///
/// 2. 模块管理
///
/// 2.1 模块状态
///
/// // 获取模块实例(自动调用 Awake 方法)
/// var module = MySingletonModule.Instance;
///
/// // 获取模块名称
/// var name = module.Name;
///
/// // 获取模块标签
/// var tags = module.Tags;
///
/// // 开始运行模块
/// module.Start();
///
/// // 停止运行模块
/// module.Stop();
///
/// // 重置模块状态
/// module.Reset();
///
/// 2.2 事件系统
///
/// // 注册事件
/// module.Event.Register(id, callback);
///
/// // 注销事件
/// module.Event.Unregister(id, callback);
///
/// // 通知事件
/// module.Event.Notify(id, args);
///
/// 2.3. 事件特性
///
/// // 定义模块
/// public class MyModule : XModule.Base<MyModule> { }
///
/// // 定义事件
/// public enum MyEvent
/// {
/// Event1,
/// Event2,
/// Event3,
/// }
///
/// // 标记事件
/// public class MyListener {
/// // 在类中使用事件特性标记方法
/// [XModule.Event(MyEvent.Event1, typeof(MyModule), false)]
/// public void OnEvent1() { }
///
/// // 支持单次回调的事件(通知一次后自动注销)
/// [XModule.Event(MyEvent.Event2, typeof(MyModule), true)]
/// public void OnEvent2(params object[] args) { }
///
/// // 支持无模块绑定的事件
/// [XModule.Event(MyEvent.Event3, null, false)]
/// public void OnEvent3(int param1, bool param2) { }
///
/// // 支持静态方法
/// [XModule.Event(MyEvent.Event3, typeof(MyModule), true)]
/// public static void OnEvent3Static() { }
/// }
///
/// // 获取类型中标记的所有事件特性
/// var events = XModule.Event.Get(typeof(MyListener));
///
/// // TODO: 根据标记的事件特性注册事件
///
/// 特性说明:
/// - 支持事件标识(`ID`)、模块类型(字段名必须为 `Instance`)及单次回调(`Once`)等标记选项
/// - 支持实例方法和静态方法等种方法签名(无参、有参、返值),支持继承类中的事件特性
/// - 特性标记只维护事件的元数据,业务层需自行实现事件注册/注销的行为,可参考 `XView` 模块
///
/// 更多信息请参考模块文档。
///
public class XModule
{
///
/// 定义了模块的基础接口,包含模块的基本属性和生命周期方法。
///
public interface IBase
{
///
/// 获取模块名称。
///
string Name { get; }
///
/// 获取或设置模块是否启用。
///
bool Enabled { get; set; }
///
/// 获取模块的事件管理器。
///
XEvent.Manager Event { get; }
///
/// 获取或设置模块的日志标签。
///
XLog.LogTag Tags { get; set; }
///
/// 模块初始化时调用。
///
void Awake();
///
/// 模块启动时调用。
///
/// 启动参数
void Start(params object[] args);
///
/// 重置模块状态。
///
void Reset();
///
/// 停止模块运行。
///
void Stop();
}
///
/// 提供了模块的基础实现,包含默认的生命周期管理和事件系统集成。
///
public class Base : IBase
{
internal string name;
///
/// 获取模块名称,如果未设置则返回类型名称。
///
public virtual string Name
{
get
{
name ??= GetType().Name;
return name;
}
}
///
/// 获取或设置模块是否启用。
///
public virtual bool Enabled { get; set; }
internal XEvent.Manager @event;
///
/// 获取模块的事件管理器,如果未初始化则创建新实例。
///
public virtual XEvent.Manager Event
{
get
{
@event ??= new XEvent.Manager();
return @event;
}
}
internal XLog.LogTag tags;
///
/// 获取或设置模块的日志标签,包含模块名称和哈希值。
///
public virtual XLog.LogTag Tags
{
get
{
tags ??= XLog.GetTag().Set("Name", Name).Set("Hash", GetHashCode().ToString());
return tags;
}
set { tags = value; }
}
///
/// 模块初始化时调用,记录日志。
///
public virtual void Awake()
{
XLog.Notice("Module has been awaked.", Tags);
}
///
/// 模块启动时调用,设置启用状态并记录日志。
///
/// 启动参数
public virtual void Start(params object[] args)
{
Enabled = true;
XLog.Notice("Module has been started.", Tags);
}
///
/// 重置模块状态,记录日志。
///
public virtual void Reset()
{
XLog.Notice("Module has been reseted.", Tags);
}
///
/// 停止模块运行,清理事件并重置状态。
///
public virtual void Stop()
{
Enabled = false;
Event?.UnregisterAll();
Reset();
XLog.Notice("Module has been stopped.", Tags);
}
}
///
/// 提供了模块的单例模式支持,自动管理模块实例的生命周期。
///
/// 模块类型
public class Base : Base where TModule : IBase, new()
{
internal static TModule instance;
///
/// 获取模块的单例实例,如果未创建则自动创建并初始化。
///
public static TModule Instance
{
get
{
if (instance == null)
{
instance = new TModule();
instance.Awake();
}
return instance;
}
}
}
///
/// 定义了事件的标记特性,使用此特性可以为事件定义参数。
///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class Event : Attribute
{
///
/// 事件标识。
///
public int ID { get; internal set; }
///
/// 模块类型。
///
public Type Module { get; internal set; }
///
/// 单次回调。
///
public bool Once { get; internal set; }
///
/// 模块实例。
///
public IBase Target { get; internal set; }
///
/// 回调函数。
///
public MethodInfo Callback { get; internal set; }
public Event(object id, Type module = null, bool once = false)
{
ID = id == null ? -1 : id.GetHashCode();
Module = module;
Once = once;
}
///
/// 视图元素特性的全局缓存。
///
internal static readonly Dictionary> cached = new();
///
/// 根据类型获取视图元素标记的特性。
///
/// 目标类型
/// 标记的特性列表
public static IReadOnlyList Get(Type type)
{
if (type == null) return null;
if (!cached.TryGetValue(type, out var events))
{
events = new List();
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var method in methods)
{
var attrs = method.GetCustomAttributes();
foreach (var attr in attrs)
{
if (attr.Module != null)
{
if (!typeof(IBase).IsAssignableFrom(attr.Module))
{
XLog.Error("XModule.Event: module {0} does not implements {1}.", attr.Module, typeof(IBase));
continue;
}
else
{
var prop = attr.Module.GetProperty("Instance", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
if (prop != null) attr.Target = prop.GetValue(null) as IBase;
if (attr.Target == null)
{
XLog.Error("XModule.Event: unable to find instance of module {0}.", attr.Module);
continue;
}
}
}
attr.Callback = method;
events.Add(attr);
}
}
cached.Add(type, events);
}
return events;
}
}
}
}