# Init(args)：Unity中的依赖注入神器！

> Init(args)是一款专为Unity打造的依赖注入框架，从头开始设计，旨在与您熟悉的传统Unity工作流程无缝融合。通过在Inspector中拖放引用到字段，已经为对象注入依赖提供了一个良好的基础。因此，Init(args)的目标不是在此方面重新造轮子，而是修复其中的各种不足，释放其全部潜力。

- 原文：https://www.interestcreator.com/initargs/
- 站点：https://www.interestcreator.com/
- 发布：2023-08-01
- 更新：2023-08-02
- 分类：Unity插件
- 标签：Unity、unity 编辑器扩展、Unity插件、unity编辑器扩展工具

## 正文

![](https://www.interestcreator.com/wp-content/uploads/2023/08/1690898519-c4ca4238a0b9238.webp)





Init(args)是一款专为Unity打造的依赖注入框架，从头开始设计，旨在与您熟悉的传统Unity工作流程无缝融合。





## 什么是Init(args)？





Init(args)是一个Unity的依赖注入框架，其关键目标是确保所有工具的各个方面与本地编辑器体验无缝融合。





## Init(args)解决了哪些问题？





Unity编辑器的场景化工作流程是一个强大的工具，通过在Inspector中拖放引用到字段，已经为对象注入依赖提供了一个良好的基础。因此，Init(args)的目标不是在此方面重新造轮子，而是修复其中的各种不足，释放其全部潜力。





在原始Unity中，所有组件都需要自己找到所依赖对象的引用。其中一种方法是添加序列化字段，让用户可以使用Inspector来分配引用。虽然这样做很方便，但也存在一些限制，不能在每种情况下使用：



- 不能将对象分配给接口字段



- 不能跨场景或预制件分配对象



- 反复将相同的管理器拖放到组件中很繁琐



- 要切换管理器到不同的管理器，必须手动更新所有组件的引用



- 不能分配动态值，使得处理本地化文本、可寻址资源和随机化值等更困难





由于这些限制，组件通常不得不将序列化字段与其他解决依赖的方法相结合：单例、GetComponent、GetComponentInChildren、FindObjectOfType、FindWithTag、静态方法等等。这种混合使用的方式也带来了自己的问题：



- 可能会在组件的代码中增加很多不必要的噪音



- 依赖可能隐藏在代码的任何地方



- 依赖通常是硬编码到特定类中



- 依赖是使用硬编码的搜索方法定位的





即使通过这些方法组合成一个相对体面的组件，也很可能几乎不可能为其编写任何单元测试！





Init(args)可以为您解决所有这些问题。





## 保持简单





使用Init(args)，您不必花费大量时间学习复杂的概念，比如绑定、容器、装饰器或上下文……实际上，您可以仅使用Inspector来满足大部分的依赖注入需求！不过，现在的灵活性更强。





当您想要在代码中初始化对象时，您仍然可以使用您已经熟悉的所有命令，比如AddComponent和Instantiate——只是现在您可以传入一些参数。





这个小而重要的变化意味着，您的组件不再是封闭的孤岛，也不再是隐藏依赖关系的黑匣子；当您用其依赖项实例化一个组件时，您可以确信它将正常工作。这也意味着为组件编写单元测试变得轻松愉快，甚至让您兴奋不已！





## 纯净的依赖注入





Init(args)的主要重点是在场景对象和预制件中，以及在代码中实现纯净的依赖注入。这意味着尽可能地少使用反射，而是使用泛型方法和接口来提供强类型的依赖传递路径。





这种方法有很多好处，比如与基于反射的解决方案相比具有更高的性能，并且在编译时尽早捕获用户错误。这种快速失败的设计在编辑器方面也有所体现，在编辑模式下会向控制台记录有关场景中缺少参数的警告。





纯净的依赖注入还有助于提高项目的可读性；对象之间的依赖关系不会被混淆，您可以轻松地在IDE和编辑器中跟踪依赖的轨迹——这在调试应用程序时至关重要。





点缀一些魔法的力量...除了提供所有Unity中纯净的依赖注入工具外，Init(args)还提供了一个强大的系统，可以像魔法一样创建共享实例，并自动将它们传递给客户端（或者，如果您愿意，限制在特定场景或转换层次结构中）。





这些共享实例被称为“服务”，您可以通过为任何类添加[Service]属性来创建一个新的服务。您可以将服务视为增强版的单例。





更容易创建（只需添加一个属性）。



自动传递给所有客户端组件。



服务可以轻松使用其他服务（无需执行顺序问题）。



当需要时，可以为个别组件覆盖服务参数。



支持从Addressables、Resources文件夹和场景加载服务。



在单元测试期间，服务可以替换为模拟对象。





服务系统使用了反射，但仅在初始化时使用，之后访问缓存的服务非常快速。





## Inspector特性：





完全支持接口——直观的拖放和下拉式Inspector界面。



值提供程序——动态参数，例如随机值或运行时对象的引用。



Null参数保护——在编辑模式和运行时获得缺少参数的警告。



跨场景引用——将对象分配给其他场景的字段。



服务标签——从上下文菜单将任何组件变成服务。





## 代码特性：





[Service]属性——轻松创建全局共享服务，并自动注入客户端。



带参数的AddComponent。



带参数的Instantiate。



带有组件和参数的新GameObject。



智能执行顺序——根据它们的依赖项对对象进行初始化，避免执行顺序相关的问题。



Null / NullOrInactive——轻松测试接口类型变量是否包含一个已销毁的对象。



包装器——将普通的C#对象附加到游戏对象。



只读支持——在初始化期间为只读字段和属性分配值。





此外，还包含一个带有完全功能的示例游戏的演示场景！
