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。

更多信息参考:

哪些类是源码生成器生成的目标?

满足以下所有条件时自动生成代码:

    1. 所在程序集引用了 VContainer.asmdef 的类。
    1. 满足以下条件之一:
    • 附加了 [Inject] 特性。
    • 作为任何 Register* 方法的参数指定的类型。
    1. 未标记 [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>();
        }
   }
posted @   凌雪寒  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示