You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity-C# MVC模式下Service类集合的通用获取器实现问询

嘿,这个需求完全贴合Unity MVC架构的实用场景啊,我来给你一套落地性拉满的实现方案:

1. 先完善Service抽象类的基础实现

先把你提到的ServiceAbstract补全,它要持有App实例的引用,构造函数传入App确保子类能访问核心上下文:

public abstract class ServiceAbstract
{
    // 只读的App实例引用,子类可以直接调用
    protected App AppInstance { get; }

    protected ServiceAbstract(App app)
    {
        AppInstance = app ?? throw new ArgumentNullException(nameof(app), "App实例不能为null");
    }

    // 可选:给子类加一个初始化钩子,App创建Service后统一触发
    public virtual void Initialize() { }
}
2. 实现App类的Service容器与通用获取器

App类里用Dictionary<Type, ServiceAbstract>作为容器存储所有Service,同时负责统一创建这些Service,再写一个泛型方法做类型安全的通用获取:

public class App : MonoBehaviour
{
    // Unity常用单例模式,方便全局访问(不需要的话可以去掉)
    public static App Instance { get; private set; }

    // Service容器:用Type作为键,确保每个Service类型唯一
    private Dictionary<Type, ServiceAbstract> _serviceContainer = new Dictionary<Type, ServiceAbstract>();

    private void Awake()
    {
        // 单例初始化逻辑(可选)
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject);

        // 在这里创建并注册所有业务Service
        InitializeServices();
    }

    private void InitializeServices()
    {
        // 创建具体Service实例,传入当前App实例
        RegisterService(new UserService(this));
        RegisterService(new GameDataService(this));
        RegisterService(new AudioService(this));

        // 统一调用所有Service的初始化方法(如果有)
        foreach (var service in _serviceContainer.Values)
        {
            service.Initialize();
        }
    }

    // 内部注册方法,避免重复注册同一类型Service
    private void RegisterService(ServiceAbstract service)
    {
        Type serviceType = service.GetType();
        if (_serviceContainer.ContainsKey(serviceType))
        {
            Debug.LogWarning($"Service类型 {serviceType.Name} 已存在,跳过重复注册");
            return;
        }
        _serviceContainer.Add(serviceType, service);
    }

    // 通用获取器:泛型方法确保类型安全,避免强制转换
    public T GetService<T>() where T : ServiceAbstract
    {
        if (_serviceContainer.TryGetValue(typeof(T), out var service))
        {
            return service as T;
        }

        // 这里可以根据需求选择抛出异常或返回null
        throw new InvalidOperationException($"未找到类型为 {typeof(T).Name} 的Service,请先在App中注册");
        // 或者 return null;
    }
}
3. 编写具体的业务Service子类

比如一个处理用户数据的Service示例:

public class UserService : ServiceAbstract
{
    public UserService(App app) : base(app) { }

    // 重写初始化方法做业务初始化(可选)
    public override void Initialize()
    {
        // 可以通过AppInstance访问其他Service或App全局数据
        var gameDataService = AppInstance.GetService<GameDataService>();
        LoadLocalUserProfile();
    }

    public void LoadLocalUserProfile()
    {
        // 具体业务逻辑:比如读取本地存档、同步云端数据等
    }
}
4. 在Unity业务代码中使用

比如在MVC的Controller里获取Service:

public class UserController : MonoBehaviour
{
    private UserService _userService;

    private void Start()
    {
        // 通过App单例快速获取目标Service
        _userService = App.Instance.GetService<UserService>();
        _userService.LoadLocalUserProfile();
    }
}

这个方案的优势:

  • 完全匹配你的需求:App统一创建、管理Service,容器存储+泛型通用获取器
  • 扩展性极强:新增Service只需继承ServiceAbstract,在App的InitializeServices里注册即可
  • 类型安全:泛型获取器避免了强制转换的风险,编译期就能发现类型错误
  • 适配Unity生命周期:利用Awake做初始化,单例模式确保全局唯一

内容的提问来源于stack exchange,提问作者Jobbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:17:13