Zenject框架(二)
Hello World 示例
using Zenject;
using UnityEngine;
using System.Collections;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<string>().FromInstance("Hello World!");
Container.Bind<Greeter>().AsSingle().NonLazy();
}
}
public class Greeter
{
public Greeter(string message)
{
Debug.Log(message);
}
}
按以下步骤操作后,可以运行该例。
- 在Unity中创建新场景
- 在Hierarchy面板中点击右键选择
Zenject -> Scene Context
- 在Project面板中点击右键选择
Create -> Zenject -> MonoInstaller
.命名为TestInstaller.cs - 把TestInstaller脚本拖拽到场景中的某一物体上(新建物体或使用已存在的物体都无关紧要)
- 选中SceneContext游戏对象,在Inspector面板中,找到“Installer”属性点击“+”新增一行,把TestInstaller所在的物体拖拽上去
- 打开TestInstaller脚本并将上面的代码粘贴进去
- 通过选择
Edit - > Zenject - >Validate Current Scene
或按Shift + Alt + V来验证场景。(请注意,此步骤不是必需的,但是是启动的良好做法) - 运行
- 另请注意,您可以使用快捷方式Ctrl+Shift+R“验证然后运行”。验证通常很快,这不会给运行游戏增加明显的开销,并且当它确实检测到错误时,迭代起来要快得多,因为您可以避免启动时间。
- 观察Unity控制台的输出
SceneContext 脚本是应用程序的入口点,Zenject在开始场景之前设置所有各种依赖项。要向Zenject场景添加内容,您需要将Zenject中引用的内容编写为“Installer”,它将声明所有依赖关系及其相互之间的关系。标记为“NonLazy”的所有依赖项在Installers运行后自动创建,这就是我们在上面添加的Greeter类在启动时创建的原因。如果这对你没有意义,请继续阅读!
注入
有许多不同的方法来声明容器(Container)的依赖关系,这将在下一节中介绍。还有几种方法可以将这些依赖项注入到类中。这些是:
1-构造函数注入
public class Foo
{
IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
}
2-字段注入
public class Foo
{
[Inject]
IBar _bar;
}
字段注入在调用构造函数后立即进行。标记有该[Inject]属性的所有字段都在容器(container)中查找并给出一个值。请注意,这些字段无论是私有还是公共的都会发生注入。
3-属性注入
public class Foo
{
[Inject]
public IBar Bar
{
get;
private set;
}
}
除了应用于C#属性之外,属性注入与字段注入相同。 就像字段一样,在这种情况下,属性也可以是私有的或公共的。
3-方法注入
public class Foo
{
IBar _bar;
Qux _qux;
[Inject]
public Init(IBar bar, Qux qux)
{
_bar = bar;
_qux = qux;
}
}
方法注入注入与构造函数注入非常相似。
请注意以下事项:
-因为MonoBehaviours不能有构造函数, 因此在MonoBehaviours中使用方法注入是推荐的方式。
-
注入方法的数量可以是任意个。在这种情况下,它们按照从基类到派生类的顺序调用。这有助于避免需要通过构造函数参数将派生类中的许多依赖项转发到基类,同时还保证基类注入方法首先完成,就像构造函数的工作原理一样。
-
注入方法在所有其他注入类型之后被调用。通过这种设计以便注入方法可用于执行初始化逻辑,这可能会使用注入的字段或属性。另请注意,如果您只想执行某些初始化逻辑,则可以将参数列表保留为空。
-
您可以放心地假设您通过注入方法接收的依赖项本身已经被注入(唯一的例外是在具有循环依赖项的情况下)。如果使用注入方法执行一些基本初始化,这可能很重要,因为在这种情况下,您可能还需要初始化给定的依赖项
-
但请注意,使用注入方法初始化逻辑通常不是一个好主意。通常最好使用IInitializable.Initialize或Start()方法,因为这将允许首先创建整个初始对象图。
建议
与字段/属性注入相比,使用构造函数/方法注入是更好的练习方式。 -
构造函数注入强制依赖只在类创建时解析一次,这通常是您想要的。在大多数情况下,您不希望为初始依赖项公开公共属性,因为这表明它可以更改。
-
构造函数注入保证类之间没有循环依赖关系,这通常是一件坏事。当使用其他注入类型时,Zenject确实允许循环依赖,例如方法/字段/属性注入
-
对于您决定在没有DI框架(如Zenject)的情况下重用代码,构造函数/方法注入更具可移植性。您可以对公共属性执行相同操作,但它更容易出错(忘记初始化一个字段并使对象处于无效状态的情况更容易发生)
-
最后,当另其他程序员读取代码时,构造函数/方法注入能清楚地表明类的所有依赖关系。他们可以简单地查看方法的参数列表。这也很好,因为当一个类有太多的依赖关系时会更明显,因此应该拆分(因为它的构造函数参数列表看起来很长)