场景绑定(Scene Bindings)
在许多情况下,你有很多MonoBehaviour已经被添加到Unity编辑器的场景中(在编辑时而不是运行时),并且你想要将这些MonoBehaviour添加到Zenject容器中,以便它们可以被注入其他类。
这样做的通常方法是在安装器中添加对这些对象的公共引用,如下所示:
public class Foo : MonoBehaviour
{
}
public class GameInstaller : MonoInstaller
{
public Foo foo;
public override void InstallBindings()
{
Container.BindInstance(foo);
Container.Bind<IInitializable>().To<GameRunner>().AsSingle();
}
}
public class GameRunner : IInitializable
{
readonly Foo _foo;
public GameRunner(Foo foo)
{
_foo = foo;
}
public void Initialize()
{
...
}
}
这种方法可以,但在某些情况下,这可能会很麻烦。例如,允许向场景添加任意数量的Enemy
对象,并且还希望将所有这些Enemy
对象添加到Zenject容器中。在这种情况下,您必须手动拖动每个对象到安装器的检视面板中。这很容易出错,因为它很容易忘记,或者删除Enemy
游戏对象后却忘记在检查面板删除安装器的空引用等。
另一种方法是使用FromComponentInHierarchy
绑定方法,如下所示:
public class GameInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Foo>().FromComponentInHierarchy().AsTransient();
Container.Bind<IInitializable>().To<GameRunner>().AsSingle();
}
}
现在,每当需要类型为Foo的依赖项时,zenject将在整个场景中搜索任何类型为Foo的MonoBehaviours。每次要查找某个特定类型依赖项时都以这种方式进行,这与Unity的FindObjectsOfType
方法非常相似。请注意,因为此方法是一个非常繁重的操作,所以最好将其标记为AsCached或AsSingle:
public class GameInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Foo>().FromComponentInHierarchy().AsCached();
Container.Bind<IInitializable>().To<GameRunner>().AsSingle();
}
}
这样,查找过程只会在第一次需要的时候进行,而不是每次注入都会进行。注意,需要查找多个Foo类型时,可以使用FromComponentsInHierarchy
(注意这儿是复数形式)
另一种方法是使用ZenjectBinding
组件。您可以通过将ZenjectBinding
组件添加到要自动添加到Zenject容器的同一游戏对象来完成此操作。
例如,在场景中有一个Foo
类型的MonoBehaviour ,则只需将ZenjectBinding
组件添加到同一个物体上,然后将Foo组件拖动到ZenjectBinding
组件的Component
属性中。
然后,安装器改为:
public class GameInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<IInitializable>().To<GameRunner>().AsSingle();
}
}
ZenjectBinding
组件具有以下属性:
- Bind Type-我们在这里确定要使用的“ contract type ”。它可以设置为以下任何值:
* Self
这相当于我们这样做的第一个例子:
Container.Bind<Foo>().FromInstance(_foo);
等价地:
Container.BindInstance(_foo);
因此,如果我们复制这个游戏对象以便得到多个包含Foo
组件(还有ZenjectBinding
组件)的游戏对象,它们都将以这种方式绑定到容器上。因此,在执行此操作之后,我们需要将上面GameRunner的参数改为List<Foo>
否则将抛出Zenject异常(有关列表绑定的信息,请参阅后续“List Bindings”章节)。
* AllInterfaces
此绑定类型等效于以下内容:
Container.BindInterfacesTo(_foo.GetType()).FromInstance(_foo);
注意,这种这种情况下,GameRunner
的构造函数的参数类型必须是IFoo
类型,如果是Foo
类型,zenject将会抛出异常,因为BindInterfaces
方法只能绑定接口而不能绑定具体的类型,如果你需要绑定具体的类型,你可以使用:
* AllInterfacesAndSelf
此绑定类型等效于以下内容:
Container.BindInterfacesAndSelfTo(_foo.GetType()).FromInstance(_foo);
这种方式与AllInterfaces
类似,但除了绑定接口外,还可以直接绑定具体的类
* BaseType
此绑定类型等效于以下内容:
Container.Bind(_foo.GetType().BaseType()).FromInstance(_foo)
- Identifier - 此值可以在大多数时间保留为空。它将确定用作绑定标识符的内容。例如,当设置为“Foo1”时,它相当于执行以下操作:
Container.BindInstance(_foo).WithId("Foo1");
-
Use Scene Context- 这是可选的,但在您希望将GameObjectContext内的依赖项绑定到SceneContext的情况下非常有用。您也可以将SceneContext正确拖动到Context,但这个标志更容易一些。
-
Context -这是完全可选的,在大多数情况下应该保留未设置状态。这将决定
Context
应用绑定的内容。如果未设置,它将使用游戏对象所处的任何上下文。在大多数情况下都是SceneContext
,但如果它处于GameObjectContext
中,它将被绑定到GameObjectContext
的容器上。此字段的一个重要用例是当组件处于GameObjectContext
中时,允许将SceneContext
拖动到此字段中。这允许您将此MonoBehaviour视为GameObjectContext
提供的整个子容器的Facade(参考外观模式)。
网友评论