StrangeIOC使用流程(一)
首先这个框架可以在assetStore上下载到, 也可以在GitHub上获取,直接搜索StrangeIOC就可以, AssetStore上下载的更简洁,除了有一个examples 其余都是框架脚本, GitHub上下载的则有更多的学习文档以及其他附带的东西.. 先附两张图
1、Root 是整个框架的起点,是挂在物体上的,继承自ContextView 间接继承自MonoBehavior 他的主要功能是创建Context(环境)
public class Demo1ContextView : ContextView {
private void Awake()
{
this.context = new Demo1Context(this);
}
}
2,接着创建一个Demo1Context 继承MVCSContext 主要用来绑定 需要实现父类的构造函数和一个绑定函数
public class Demo1Context : MVCSContext {
public Demo1Context(MonoBehaviour view) : base(view) { }
/// <summary>
/// 四种绑定
/// 1.model (M)
/// 2.serivce (S)
/// 3.command (C)
/// 4.mediator (V)
/// </summary>
protected override void mapBindings()
{
/// 四种绑定
/// 1.model (M)
/// 2.serivce (S)
/// 3.command (C)
/// 4.mediator (V)
//创建一个StartCommand 在上边的绑定初始化后进行调用
//commandBinder.Bind(ContextEvent) //把一个命令和一个枚举类型做绑定, 枚举类型已经提供
commandBinder.Bind(ContextEvent.START).To<StartCommand>().Once();// 把某个事件和某个Command绑定上,这个是StrangeIOC框架绑定开始事件, 自动调用StartCommand命令(会调用这个命令中的Execute方法) 只触发一次后解绑
}
}
3,创建一个控制器继承Command类,
public class StartCommand : Command {
public override void Execute()
{
Debug.Log("被调用");
}
}
4.创建model层 用来存储数据
public class ScoreModel{
public int score { get; set; }
}
5创建service 层
先有接口, 再去做实现, 可以在后期项目做接口变动时只修改实现就可以了
public interface IScoreService {
void RequestScore(string url); // 取得分数 //异步方法,没有返回值
void OnReceivesScore();//收到上边方法调用后 服务器端发送来的分数
void UpdataScore(string url, int score);//更新分数 服务器地址, 更新到服务器分数
}
6,实现service接口 ///虚拟数据, 暂时不含服务器通讯
public class ScoreService : IScoreService
{
public void RequestScore(string url)
{
Debug.Log("向地址" + url + "发送请求分数");
OnReceivesScore();
}
public void OnReceivesScore()
{
int score = Random.Range(0, 100);//模拟分数
}
public void UpdataScore(string url, int score)
{
Debug.Log("更新到" + url + "新分数:" + score);
}
}
7.view层,挂在一个游戏物体上
public class CubeView : View { //此层只做显示, 不知道任何数据也取不到
Text scoreText; //Text 组件, 分数不会在这一层中做处理,而是在model层
void Init()
{
scoreText = GetComponentInChildren<Text>();
}
private void Update()
{
transform.Translate(new Vector3(Random.Range(-1, 2), Random.Range(-1, 2), Random.Range(-1, 2)) * .2f);
}
private void OnMouseDown()
{
Debug.Log("onmousedown");
}
public void UpdateScore(int score)//用来更新分数显示, 不处理分数逻辑 mediator负责调用.,一般一个view对应一个mediator...mediator是什么..看CubeMediator类
{
scoreText.text = score.ToString();
}
}
8.View的中介层 Mediator
public class CubeMediator : Mediator { //用来处理CubeView和外界的交互,这个类需要在Context中注册到一个View层的类中,让框架进行匹配或者说处理 //这个类会在绑定后自动添加到绑定的对象(gameObject)上;
[Inject] //对一个属性进行注入 注入后StrangeIOC会自动对这个属性进行赋值 .目的是减少层与层之间的交互
public CubeView cubeView { get; set; }
public override void OnRegister() //在所有属性注入完成后会自动调用,保证能够访问到属性
{
Debug.Log(cubeView.name);
cubeView.Init();
}
public override void OnRemove()//当mediator对应的view被销毁时自动调用(经过测试没有被调用)-未解
{
Debug.Log(this.name);
}
}
9.更新分数的显示-- 通过mediator调用command 通过command调用services的request方法来取得分数,这里需要使用模块与模块之间触发的机制 -- IEventDispatcher 派发器, 这样避免了模块之间直接去调用, 同样是为了解耦
首先创建请求分数的Command层
public class RequestScoreCommand : Command {
public override void Execute() //在mediator里去触发 这个方法去请求服务器里的分数
{
}
}
10.然后在CubeMediator中进行修改如下
public class CubeMediator : Mediator { //用来处理CubeView和外界的交互,这个类需要在Context中注册到一个View层的类中,让框架进行匹配或者说处理 //这个类会在绑定后自动添加到绑定的对象(gameObject)上;
[Inject] //对一个属性进行注入 注入后StrangeIOC会自动对这个属性进行赋值 .目的是减少层与层之间的交互
public CubeView cubeView { get; set; }
[Inject] //注入
public IEventDispatcher dispatcher { get; set; }
public override void OnRegister() //在所有属性注入完成后会自动调用,保证能够访问到属性
{
Debug.Log(cubeView.name);
cubeView.Init();
//通过dispatcher 发起请求分数的命令
dispatcher.Dispatch(Demo1CommandEvent.RequestScore);//发起一个Event,这个Event和哪个Command绑定,这个Command就会被调用
}
public override void OnRemove()//当mediator对应的view被销毁时自动调用(经过测试没有被调用)-未解
{
Debug.Log(this.name);
}
}
11新建枚举
public enum Demo1CommandEvent { //这个来保存这个项目中所有命令的事件
RequestScore,
}
12.在Demo1Context中添加绑定
// 3.command (C)
commandBinder.Bind(Demo1CommandEvent.RequestScore).To<RequestScoreCommand>();//把这个事件(枚举类型)和请求分数进行绑定,绑定之后就会自动调用 RequestScoreCommand的Execute方法了
13.RequestScoreCommand类中添加一个注入引用
[Inject]
public IScoreService scoreService { get; set; } //这里由于不像CubeMediator 在注入CubeView的时候 因为CubeView是挂到游戏物体上的,获得的注入唯一.这个接口可能有很多实现, 所以需要通过注入绑定的方式进行指定
14.注入绑定,在Demo1Context类中
// 2.serivce (S)
injectionBinder.Bind<IScoreService>().Bind<ScoreService>().ToSingleton();// 注入绑定指定实现的类,当需要注入IScoreService的时候才能确定,因为model和service只需要一个对象(数据和服务器请求,不像挂载游戏物体产生多个实例)所以可以通过.ToSingleton设置为单例只在工程中生成一个
15.注入后就可以在requestScoreCommand类中的Execute方法中调用了
public class RequestScoreCommand : Command {
[Inject]
public IScoreService scoreService { get; set; } //这里由于不像CubeMediator 在注入CubeView的时候 因为CubeView是挂到游戏物体上的,获得的注入唯一.这个接口可能有很多实现, 所以需要通过注入绑定的方式进行指定
public override void Execute() //在mediator里去触发 这个方法去请求服务器里的分数
{
scoreService.RequestScore("http:xxxx.x.x.x.");
}
}
这里会有一个问题.由于在CubeMediator中的dispatcher派发器是类中的(局部的),会导但是派发器在CubeMediator发起请求的时候不会被调用,所以必须使用全局的派发器,在注入绑定时加一个标示就行了
[Inject(ContextKeys.CONTEXT_DISPATCHER)] //注入的方式拿到派发器类(其实是个接口)的引用 (括号中为设置成全局的派发器)
public IEventDispatcher dispatcher { get; set; } //声明一个派发器
到这里 就完成了调用服务器之前的事情. 可以发现所有类之间并没有直接联系.都是通过注入的形式去调用 附上工程链接,后续更新
https://pan.baidu.com/s/15DcIpjOPhitvhekdJ45GcQ