Skip to main content

Source Generator

caution

This feature requires Unity 2021.3 or later.

VContainer uses reflection for metaprogramming by default. However, there is an option to improve execution performance by replacing it with Roslyn Source Generator.

Source Generator is part of Roslyn's functionality as a C# compiler tool. It is a feature that allows additional source code to be plugged in without contaminating the human-written source code. Since the added code is in C#, it is more debuggable and maintainable than IL code generation or ExpressionTee at runtime. While there are programming languages out there that have mechanisms such as "macros" built into their syntax, Source Generator has one thing in common in that it generates source code at compile time. This is a standard meta-programming approach in the new .NET environment.

info

In the old version of VContainer, this feature was used by IL weaving using Mono.Cecil. Since VContainer 1.13.0, we have moved to Roslyn Source Generator.

How to enable VContainer Source Generator

1. Add VContainer.SourceGenerator.dll to your project.

Download `VContainer.SourceGenerator.dll from the release page. https://github.com/hadashiA/VContainer/releases

And Add this to somewhere under Assets/ folder in your project.

2. Mark as RoslynAnalyzer

Select VcContainer.SourceGenerator.dll in project. And, click label icon in bottom of the inspector window. Enter “RoslynAnalyzer” into the text input window in the Asset Labels sub-menu.

Then, from the inspector, do the following:

  • Go to Select platforms for plugin and disable Any Platform.
  • Go to Include Platforms and disable Editor and Standalone.

See more information:

Which classes are target to code generation?

Classes that meet the following conditions are eligible for code generation.

    1. Classes in assemblies that reference VContainer.asmdef.
    1. And one of the following is satisfied.
    • [Inject] attribute is attached to.
    • the type specified as a parameter of the any Register* method.
    1. Correct, except for types with [InjectIgnore].

If you want to explicitly add it to the target, you can control it by granting the [Inject] attribute, if you want to explicitly exclude it from the target, you can control it by granting the [InjectIgnore] attribute.

Note that classes that are targeted for code generation are [Preserve] and therefore not subject to code-stripping by IL2CPP.

Limitation

SourceGenerator acceleration is not supported for type definitions like the following. (works by reflection)

  • Nested classes
  • Struct
  • If the access level is less than internal (for example, private), even if [Inject] is added, SourceGenerator is not supported.

Remarks

With VContainer, for example, the following code (as IL) is automatically generated:

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>();
}
}