zenJect

Zenject框架(七)

2019-03-12  本文已影响0人  虫小白

BindInterfacesTo 和 BindInterfacesAndSelfTo

如果你使用了ITickable, IInitializable, 和 IDisposable 接口,代码会变成这样:

Container.Bind(typeof(Foo), typeof(IInitializable), typeof(IDisposable)).To<Logger>().AsSingle();

这有点冗长,同时也不够理想,因为假如我稍后决定Foo不再使用Tick()或者Dispose(),那我就必须同时修改安装器。
一个更好的想法可能是只以下面的方式使用接口:

Container.Bind(new[] { typeof(Foo) }.Concat(typeof(Foo).GetInterfaces())).To<Foo>().AsSingle();

这种方式足够有用并且Zenject自定义了一个这种方式的绑定方法。上面的代码相当于:

Container.BindInterfacesAndSelfTo<Foo>().AsSingle();

现在,我们可以添加或者删除Foo的接口,而安装器不用修改。
在某些情况下,你可能只需要绑定的接口,并保持Foo对其他类隐藏。在这种情况下,您可以使用BindInterfacesTo方法:

Container.BindInterfacesTo<Foo>().AsSingle()

在该例中,相当于:

Container.Bind(typeof(IInitializable), typeof(IDisposable)).To<Foo>().AsSingle();

使用Unity的检视面板配置设置

将大部分代码编写为普通C#类而不是MonoBehaviour的一个后果是,您无法使用检查面板中配置数据。但是,您可以通过在Zenject中使用下面的方式来实现此功能:

public class Foo : ITickable
{
    readonly Settings _settings;

    public Foo(Settings settings)
    {
        _settings = settings;
    }

    public void Tick()
    {
        Debug.Log("Speed: " + _settings.Speed);
    }

    [Serializable]
    public class Settings
    {
        public float Speed;
    }
}

然后,在安装器中:

public class TestInstaller : MonoInstaller<TestInstaller>
{
    public Foo.Settings FooSettings;

    public override void InstallBindings()
    {
        Container.BindInstance(FooSettings);
        Container.BindInterfacesTo<Foo>().AsSingle();
    }
}

或者,等价的:

public class TestInstaller : MonoInstaller<TestInstaller>
{
    public Foo.Settings FooSettings;

    public override void InstallBindings()
    {
        Container.BindInterfacesTo<Foo>().AsSingle().WithArguments(FooSettings);
    }
}

现在,如果我们运行场景,我们可以在检视面板中实时调整Foo类的speed值。
另一种(可以说是更好的)方法是使用ScriptableObjectInstaller而不是MonoInstaller,ScriptableObjectInstaller具有额外的优势,您可以在运行时更改您的设置,并在停止运行时自动保存这些更改。详情请见“Scriptable Object 安装器”章节。

对象图验证

概览
使用DI框架设置绑定时的工作流程通常如下:

你可以通过Edit -> Zenject -> Validate Current Scene进行验证,或者在打开要验证场景的情况下按Shift+Alt+V进行验证,这将会验证当前场景的所有安装器。然后遍历对象图并验证是否可以找到所有绑定(而实际上不会实例化任何绑定)。换句话说,它执行正常启动过程的“干运行”。在引擎盖下,这可以通过在容器中存储虚拟对象来代替实际实例化类来实现。
或者,您可以执行菜单项Edit -> Zenject -> Validate Then Run或只是按下CTRL+SHIFT+R。这将验证您打开的场景,然后如果验证成功,它将开始运行。验证通常非常快,所以相较于点击“运行”按钮这可能是一个更好的选择,特别是当你的游戏启动时间很长的时候。
请注意,这还将包括工厂和内存池,这非常有用,因为这些错误可能在启动后的某个时间才会被捕获。
有几点需要注意:

自定义验证

如果要添加自己的验证逻辑,只需将一个类继承IValidatable即可完成此操作。执行此操作后,只要您的类在某个安装器中绑定,它将在验证期间实例化,然后Validate()方法将被调用。但请注意,它所具有的任何依赖项将被注入为null(除非标记为[ZenjectAllowDuringValidation]属性)。

如果您希望验证失败,您可以在Validate方法内部抛出异常,或者只是将信息记录到控制台。自定义validatable中出现的一个常见问题是实例化无法验证的类型。通过在验证期间实例化它们,它将确保可以解决所有依赖关系。

例如,如果您创建一个直接使用Container.Instantiate<Foo>()实例化类型的自定义工厂,则Foo不会被验证,因此在运行时之前您不会发现它是否缺少某些依赖项。但是,您可以通过让工厂实现IValidatable然后在Validate()方法内部调用Container.Instantiate<Foo>()来解决此问题。

上一篇 下一篇

猜你喜欢

热点阅读