首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DI容器的简单实现

DI容器的简单实现
EN

Code Review用户
提问于 2020-04-28 18:31:23
回答 1查看 107关注 0票数 1

我决定自己做一个轻型DI容器。

我知道Zenject,等等,我想要一个非常轻的模拟。

我担心几件事:

1)在这种情况下,使用结构而不是类作为参考是正确的吗?

2)每次访问_player.Reference时,都会检查null (在UnityEngine.After中,对象的销毁不等于null,所以使用SafeIsUnityNull)

( 3)双点。我可以让操作符超载,这样它就可以代替_player.Reference.AAAAAAAAAAAAA();工作_player.AAAAAAAAAAAAA();了吗??

容器本身:

代码语言:javascript
复制
    public static class DIContainer
    {

        private static readonly Dictionary<System.Type, Object> _references = new Dictionary<System.Type, Object>();

        public static void Bind<T>(T value) where T : Object
        {

            _references[typeof(T)] = value;

        }

        public static T Resolve<T>() where T : Object
        {

            if (_references.TryGetValue(typeof(T), out Object value))
                return (T)value;

            throw new System.InvalidCastException($"DIContainer: invalid resolve object {typeof(T)}");

        }

    }

实地参考资料:

代码语言:javascript
复制
    public struct DIReference<T> where T : Object
    {

        private T _reference;
        public T Reference => !_reference.SafeIsUnityNull() ? _reference : _reference = DIContainer.Resolve<T>();

    }

安装程序:

代码语言:javascript
复制
    public abstract class SceneInstaller : MonoBehaviour
    {
        private void Awake() => InstallBindings();
        protected abstract void InstallBindings();

    }
代码语言:javascript
复制
public class LevelInstaller : SceneInstaller
{


}

使用

绑定:

代码语言:javascript
复制
    [SerializeField] private PlayerController _player;

    protected override void InstallBindings()
    {

        DIContainer.Bind(_player);

    }

参考资料:

代码语言:javascript
复制
public class Test
{

    private DIReference<PlayerController> _player;

    private void Foo()
    {

        _player.Reference.AAAAAAAAAAAAA();

    }

}
EN

回答 1

Code Review用户

发布于 2020-05-05 11:21:14

实际上,您要做的是实现Service,这与依赖注入完全相反。请参阅[这个]关于它的讨论。

请使用已经存在的解决方案.

我只想指出为什么我认为这不适合你的情况:

  1. 为什么您认为您需要更轻量级的DI容器?您是否执行了基准测试,并证明您的瓶颈是DI注射?
  2. 为什么你选择了DIReference的结构?对于一个字段来说,Struct不是一个好的选择,因为在堆上分配它是不需要的(我猜)。请参阅[这个]讨论。
  3. 你为什么要用DIReference呢?这只会使你的代码变得复杂。您不需要将其存储为任何地方的字段--您需要的实例已经保存在_references中的DIContainer中。
  4. 要指出的是,由于您的_references是静态只读字段,所以这个字典是单例的。它几乎没有引起潜在的问题,举两个例子:
    • 是否保证每次安装绑定时都不会有其他线程尝试执行相同的操作?
    • 本词典中的每一个实例也都是单一的。我的意思是,一等一等将PlayerController安装到DIContainer中的_references中,那么所有使用DIContainer类的类都可以使用它。但是你仍然可以覆盖它。为什么这会是个问题?这可能会造成巨大的GC压力,因为您将不断地在字典中覆盖PlayerController,而GC必须清理它,这可能会导致所有线程停止运行。你绝对想避免这种情况,尤其是在游戏中。

我强烈建议使用已经存在的DI解决方案。如果您担心性能,请参考[这个] benchamrks。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/241389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档