VContainer-optimization/source-generator | 优化——源码生成器
:::caution
需 Unity 2021.3 或更高版本
:::
VContainer 默认使用反射实现元编程。
可通过 Roslyn 源代码生成器 来提高性能。
源代码生成器作为 C# 编译器工具,是 Roslyn 功能的一部分。
它允许在不污染手写的源代码的情况下插入额外的源代码。
由于生成的是 C# 代码,因此比运行时生成 IL 代码或使用 ExpressionTree 更具可调试性和可维护性。
虽然有些编程语言在其语法中内置了“宏”等机制,但源代码生成器在编译时生成源代码的方式与它们有共同之处。
这是新 .NET 环境中的标准元编程方案。
:::info
在旧版本的 VContainer 中,此功能通过 Mono.Cecil
进行 IL 编织实现。
从 VContainer 1.13.0 起改用 Roslyn 方案替代旧版方案。
:::
启用 VContainer 源代码生成器步骤
1. 将 VContainer.SourceGenerator.dll
添加到项目中。
在发布页面下载 VContainer.SourceGenerator.dll
。
https://github.com/hadashiA/VContainer/releases
将其添加到项目中的 Assets/ 目录。
2. 标记为 RoslynAnalyzer
在项目中选择 VcContainer.SourceGenerator.dll
。
然后,点击检查器窗口底部的标签图标。
在 Asset Labels 子菜单的文本输入窗口中输入“RoslynAnalyzer”。
然后,在检查器中执行以下操作:
- 在 Select platforms for plugin 禁用 Any Platform。
- 在 Include Platforms 禁用 Editor 和 Standalone。
更多信息参考:
哪些类是源码生成器生成的目标?
满足以下所有条件时自动生成代码:
-
- 所在程序集引用了 VContainer.asmdef 的类。
-
- 满足以下条件之一:
- 附加了
[Inject]
特性。 - 作为任何
Register*
方法的参数指定的类型。
-
- 未标记
[InjectIgnore]
。
- 未标记
若想显式地将其添加到目标中,可以将其标记为 [Inject]
;若想显式地将其排除在目标之外,可以将其标记为 [InjectIgnore]
。
注意:生成的类型自动添加 [Preserve]
防止 IL2CPP 代码裁剪。
限制
源代码生成器不支持以下类型的定义(通过反射工作):
- 嵌套类
- 结构体
- 如果访问级别低于 internal(例如 private),即使添加了
[Inject]
,也不受源代码生成器支持。
备注
例如,VContainer 会自动生成以下代码(作为 IL):
class ClassA
{
private sealed class __GeneratedInjector : IInjector
{
public object CreateInstance(IObjectResolver resolver, IReadOnlyList<IInjectParameter> parameters)
{
I6 fromConstructor = resolver.ResolveOrParameter<I6>("fromConstructor1", parameters);
I7 fromConstructor2 = resolver.ResolveOrParameter<I7>("fromConstructor2", parameters);
return new ClassA(fromConstructor, fromConstructor2);
}
public void Inject(object instance, IObjectResolver resolver, IReadOnlyList<IInjectParameter> parameters)
{
ClassA clasA = (ClassA)instance;
I3 service = resolver.ResolveOrParameter<I3>("service3", parameters);
I4 service2 = resolver.ResolveOrParameter<I4>("service4", parameters);
allInjectionFeatureService.MethodInjectable1(service, service2);
I5 service3 = resolver.ResolveOrParameter<I5>("service5", parameters);
I6 service4 = resolver.ResolveOrParameter<I6>("service6", parameters);
classA.MethodInjectable2(service3, service4);
classA.PrivatePropertyInjectable = resolver.Resolve<I2>();
classA.PublicPropertyInjectable = resolver.Resolve<I3>();
classA.privateFieldInjectable = resolver.Resolve<I4>();
classA.PublicFieldInjectable = resolver.Resolve<I5>();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)