StrangeIoC框架

StrangeIoC MVSC框架模块说明

1.Root

1
2
3
4
5
6
7
8
9
10
using strange.extensions.context.impl;

public class WatchMenuRoot : ContextView
{
private void Awake()
{
context = new WatchMenuContext(this, true);
context.Start();
}
}

该脚本负责启动MVCS框架,需要绑定到一个GameObject上作为容器,所有需要使用StrangeIoC提供注入功能的模块都需添加到该容器内。

2.Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using strange.extensions.context.api;
using strange.extensions.context.impl;
using UnityEngine;

public class WatchMenuContext : MVCSContext
{
public WatchMenuContext() : base()
{

}
public WatchMenuContext(MonoBehaviour view, bool autoStartup) : base(view, autoStartup)
{

}
protected override void mapBindings()
{
mapModel();
mapView();
mapCommand();
commandBinder.Bind(ContextEvent.START).To<WatchMenuStartupCommand>().Once();
}
private void mapModel()
{
injectionBinder.Bind<IModel>().To<Model>().ToSingleton();
injectionBinder.Bind<IService>().To<Service>().ToSingleton();
}
private void mapView()
{
mediationBinder.Bind<View>().To<Mediator>();
}
private void mapCommand()
{
commandBinder.Bind(NotificationCenter.GET_STUFF_LIST).To<Command>();
}
}

该脚本的作用是关联整个MVSC的模块,因为各个模块之间解耦,Context则进行模块耦合,主要进行模块绑定

  1. injectionBinder.Bind

    1
    injectionBinder.Bind<IModel>().To<Model>().ToSingleton();

    把Model作为单例绑定到IModel上,每次通过[Inject]标签注入IModel对象时,获得的都是同一个Model实例

  2. mediationBinder.Bind

    1
    mediationBinder.Bind<View>().To<Mediator>();

    把Mediator绑定到View上,在向GameObject添加View脚本时会自动创建Mediator对象并绑定到该物体

  3. commandBinder.Bind

    1
    commandBinder.Bind(NotificationCenter.GET_STUFF_LIST).To<Command>();

    把NotificationCenter.GET_STUFF_LIST绑定到Command上,当派发上述指令时,会创建一个Command实例并运行

  4. commandBinder.Bind(ContextEvent.START)

    1
    commandBinder.Bind(ContextEvent.START).To<WatchMenuStartupCommand>().Once();

    Once()立即执行并解除绑定

3.StartupCommand

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using strange.extensions.command.impl;
using strange.extensions.context.api;
using UnityEngine;

public class WatchMenuStartupCommand : EventCommand
{
[Inject(ContextKeys.CONTEXT_VIEW)]
public GameObject contextView { get; set; }

GameObject go;
public override void Execute()
{
go = contextView.transform.Find("menu-stuff").gameObject;
go.AddComponent<MenuStuffView>();
}
}

绑定了Root脚本的GameObject注入进来,将View添加到各个对应的物体上,同时Mediator也会同步添加。

4.View

  1. 视图类负责显示相关的逻辑,一般无法访问数据同时也不会调用请求接口,只通过注入的IEventDispatcher与Mediator进行通讯
1
2
3
4
5
6
7
8
9
10
11
public class MenuHomeView : View
{

[Inject(ContextKeys.CONTEXT_DISPATCHER)]
public IEventDispatcher dispatcher { get; set; }

public void Init()
{

}
}

5.Mediator

  1. 中介类作为通信中心,负责消息转发,可以将View的消息转发给其他模块,也可以接收其他模块的消息,然后通知到View
  2. 通过注入拿到View对象
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MenuHomeMediator : EventMediator
{
[Inject]
public MenuHomeView view { get; set; }
public override void OnRegister()
{
view.Init();
}
public override void OnRemove()
{

}
}

6.Command

  1. 该类用于数据请求和数据处理,执行具体的代码(工具人)
  2. 通过注入拿到Model和Service对象
  3. 如果有异步操作,需要Retain() Release()配合,保证不被垃圾回收销毁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MenuRoomCommand : EventCommand
{
[Inject]
public IRoomDataModel model { get; set; }
[Inject]
public IRoomDataService service { get; set; }
public override void Execute()
{
Retain();
dispatcher.AddListener(NotificationCenter.GET_ROOM_LIST_MENU, GetRoomListHandler);
}
private void GetRoomListHandler()
{
dispatcher.RemoveListener(NotificationCenter.GET_ROOM_LIST_MENU, GetRoomListHandler);
service.AsyncGetData();
Release();
}

}

7.Model&Service

  1. Model用于数据存储
  2. Service用于远程请求

8.工作中遇到过的问题

  1. 禁止从service向command发消息,否则会生成多个command监听事件导致事件重复触发。例如command监听mediator的消息执行了一个函数,该函数内有service的函数且在函数内service向command发送消息,导致生成两个command对象。
  2. 跨上下文context需要在绑定函数内进行非空判断,否则返回场景会报错。
  3. 如果View成功绑定到物体上,但Mediator未能正常生成并加载,需要保证View所在物体必须是Root的子物体。
  4. 不能在View中注入其他View,否则会导致View绑定失败。

StrangeIoC框架
https://baifabaiquan.cn/2022/10/28/StrangeIoC框架/
作者
白发败犬
发布于
2022年10月28日
许可协议