读一读

injectionBinder.Bind<IPositionServise>().To<LinePositionServise>().ToSingleton().CrossContext();

加上CrossContext()就可以声明这个绑定是跨上下文的,也就是说在别的Context下也可以通过IPositionServise类型来注入LinePositionServise实例。(没试验过)


先看一下绑定

protected override void mapBindings()
{
    injectionBinder.Bind<CameraInitSignal>().ToSingleton();//不声明为单例好像就不行
    mediationBinder.Bind<CamerView>().To<CamerViewMediator>();
    commandBinder.Bind<CameraInitSignal>().To<CameraInitCommand>();
}

View接收到用户的命令交互,发送命令给Mediator

using strange.extensions.mediation.impl;
using strange.extensions.signal.impl;

public class CamerView : View {

    //实例化一个局部的Signal,相当于局部的dispatcher
    public Signal<int> ViewInitSignal = new Signal<int>();

    private void OnMouseDown()
    {
        //发送命令
        ViewInitSignal.Dispatch(10);
    }
}

Mediator层

using UnityEngine;
using strange.extensions.mediation.impl;

public class CamerViewMediator : Mediator {

    [Inject]
    public CamerView View { get; set; }

    [Inject]//通过注入的方式获取全局的Signal
    public CameraInitSignal signal { get; set; }

    public override void OnRegister()
    {
        //为View局部的Signal监听
        View.ViewInitSignal.AddListener(OnCameraInit);
    }

    private void OnCameraInit(int num)
    {
        Debug.Log(10);
        //发送全局的Signal,调动绑定好的Command
        signal.Dispatch(num);
    }
}

Command层

using UnityEngine;
using strange.extensions.command.impl;

public class CameraInitCommand : Command {

    [Inject]//注入的方式获取传递的参数
    public int Num { get; set; }

    public override void Execute()
    {
        Debug.Log("Hello World Signal" + Num);
    }
}

剩下回调什么的就没必要继续了,主要想说说的是一个局部的Signal,和一个全局的Signal,还有前面Event没有提到的全局事件的传参,都是通过注入的方式,对应上类型就行,StrangIoc会自动识别的,不需要手动去Bind。


StrangeIoc默认使用的是Event的方式,所以我们要重新绑定一下使用Signal的方式。在MVCSContext下,重写

public override IContext Start()
{
    base.Start();
    //程序"起点"的修改,使用StartSignal信号来触发
    StartSignal startSignal = (StartSignal)injectionBinder.GetInstance<StartSignal>();
    startSignal.Dispatch();
    return this;
}

protected override void addCoreComponents()
{
    base.addCoreComponents();

    //先解绑,再重新绑定到SignalCommandBinder
    injectionBinder.Unbind<ICommandBinder>();
    injectionBinder.Bind<ICommandBinder>().To<SignalCommandBinder>().ToSingleton();
}

protected override void mapBindings()
{
    //和以前一样绑定,不过Event的枚举变成了刚刚触发的StartSignal
    commandBinder.Bind<StartSignal>().To<StartCommand>();
}



StrangeIoc支持两种调度方式,一种是事件的形式,一种是使用信号的方式。官方推荐使用的信号的方式。相对于于使用事件,使用信号有这样的优势:

  1. 强类型的回调结果,不用强转,也比较安全。

  2. 减少垃圾。(还不清楚怎么减少)


private IPositionServise PositionServise;

[Construct]
public CubeInitCommand(IPositionServise positionServise) {
    PositionServise = positionServise;
}

使用[Construct]特性声明构造方法,如果多个构造方法,不用[Construct]声明哪个的话,就会默认使用参数最少的那个。


  1. IOC是控制反转,我们将代码内的依赖关系交给第三方(IOC容器)管理,需要什么类型时告诉工厂,这个工厂就会成产一个实例提供出来。

  2. 绑定Bind,可以理解为往这个IOC工厂内添加接口(值)与类型的映射。

  3. 注入也叫依赖注入(DI),就是一个从IOC容器中取值的过程,注入的方式包括:属性注入、接口注入、方法注入。


在对于同一Key要对应不同的Value时,可以通过ToName(object)来命名区别

injectionBinder.Bind<IPositionServise>().To<LinePositionServise>().ToSingleton();
injectionBinder.Bind<IPositionServise>().To<CirclePositionService>().ToSingleton().ToName("Circle");

只要在注入的时候指定相应的名字就可,没有名字的就不用指定

[Inject("Circle")]
public IPositionServise PositionServise { get; set; }

绑定是一个Keys对应Value的过程,通过Keys就会得到相应的Value,也就是依赖的绑定,在一个地方,我声明需要这个I接口依赖,这时候就可以通过绑定这个依赖I为具体的实现。

protected override void mapBindings ()
{
    //注入绑定,在上下文中,将需要Key类型的值注入为Value的类型实例(这里是单例)
    injectionBinder.Bind<CubePositionModel>().To<CubePositionModel>().ToSingleton();
    injectionBinder.Bind<IPositionServise>().To<LinePositionServise>().ToSingleton();

    //View中间层的绑定,CubeView实例化后会自动实例化CubeViewMediator
    mediationBinder.Bind<CubeView> ().To<CubeViewMediator> ();

    //命令绑定,key为事件的名称(这里用枚举值表示),Value就是相应的命令Command了
    commandBinder.Bind(MCCubeEvent.InitPosition).To<CubeInitCommand>();
    commandBinder.Bind(MCCubeEvent.UpdateCunePos).To<CubeUpdateCommand>();
	//绑定启动命令,此方法完成后,就会自动分发ContextEvent.START命令
	commandBinder.Bind (ContextEvent.START).To<StartCommand> ().Once();
}

捕获.PNG

Assets下的Demo就是一个Context,分为MVCS目录,我加了一个Event目录,用来保存事件的枚举,其中前缀两个大写应为字母表示是哪两个层的交互事件,后面跟的是哪个对象的事件,最后Event结尾。MVCS就不用多说了,具体的以它的层类型结尾就好了,前缀说明是哪种对象和功能的。


  1. 首先是View层被用户交互触发事件,发送命令给Mediator

  2. Mediator接受到命令,发送相应命令给Command

  3. Command层通过Service或Model层得到相应数据,进行处理,发送命令回Mediator

  4. Mediator层接收到回调的数据,更新View