VContainer-resolving/container-api | 解析——容器 API

通过 IObjectResolver 可直接访问 DI 容器。VContainer 会自动注册 IObjectResolver 并将其注入到任何需要的地方,因此你可以通过依赖注入获取实例:

例如:

class ClassA
{
    public ClassA(IObjectResolver container)
    {
        // 解析已注册的 ServiceA 实例。
        // 如果将子类注册为 ServiceA,这里返回的会是子类实例
        var serviceA = container.Resolve<ServiceA>();

        // 对 foo 对象执行依赖注入。
        // 重复注入同一个对象会覆盖已标记为 [Inject] 的属性、字段或方法。
        container.Inject(foo);

        // 为当前 GameObject 及其子物体中的所有 MonoBehaviour 执行依赖注入。
        // 无论目标 GameObject 和 MonoBehaviours 是否处于启用状态。
        container.InjectGameObject(gameObject);

        // 实例化预制体并自动注入依赖,
        // 依赖项将注入其 MonoBehaviours(及其子对象的 MonoBehaviours)中。
        // 通过其他方式创建 GameObject(例如程序化生成或从 Addressables 加载),建议使用 InjectGameObject。
        var object1 = container.Instantiate(prefab);

        // 支持与 Object.Instantiate 相同的重载方法
        var object2 = container.Instantiate(prefab, parent);
        var object3 = container.Instantiate(prefab, position, rotation, parent);
    }
}

如果经常以某种模式使用 IObjectResolver.Inject,可以考虑为其编写扩展方法。实际上,几乎每个 IObjectResolver API 都是一个扩展方法(包括前面的代码示例)。

:::tip
仅在以下情况显式使用 IObjectResolver.Resolve,其他情况建议优先使用自动注入:

虽然所有解析方式性能相近(如果使用了 IL 生成器),但直接使用 Resolve 会增加代码量且意图不够清晰。
:::

LifetimeScope 通过其 Container 属性持有 IObjectResolver 的引用。VContainer 会自动注册它,但在容器构建后通常不需要频繁使用。

class ClassA
{
    public ClassA(LifetimeScope currentScope)
    {
        // 如果需要,也可以注入 LifetimeScope,
        // 但多数情况下直接注入 ServiceA 足矣。
        var foo = currentScope.Container.Resolve<ServiceA>();
    }
}
posted @ 2025-02-17 22:23  凌雪寒  阅读(152)  评论(4)    收藏  举报