-
Notifications
You must be signed in to change notification settings - Fork 98
Source generated injection #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Source generated injection #101
Conversation
Needed to modify .gitignore too as it would ignore required project files. Thought about moving everything inside the repository into a "Reflex.Unity" Folder, but that seemed extreme, and it would break compatibility with older version UPM installs.
Create two profiles - Local Publish, publishes locally to "Reflex.Generator\Reflex.Generator.Injector\bin\Publish", only for testing, - Send to Unity, publishes directly to "Assets\Reflex\Injectors\Source-Generator", must be used to update Unity's source generator after any change in the source generator project.
Published through the "Send to Unity" publish profile defined in the Reflex.Generator.Injector project. The DLL is the only important part, for it to function as a source generator it needs to be labeled "RoslynAnalyzer" inside of Unity.
New tests pass as expected. Strangely though, 4 old tests fail, I switched branches to the main and ran the same tests still failed, not sure why, maybe because I'm using Unity 6. Nonetheless, it doesn't seem to be my fault, but I suppose the pull request will make it clear.
Bug was caused by scanning global namespace of compilation instead of global namespace of assembly. Updated Unity source generator DLL.
…r if Failed Test will cause a compilation error if MockParent.MockUsage object doesn't implement the IAttributeInjectionContract interface.
Use only a single interface method to inject all of (fields, properties, methods). The 3 separate method calls were unnecessary as we'd never want to inject only one type of class member.
Separated the Reflex benchmark into 3 benchmark - Container Resolve (Original) - Attribute Reflection Inject - Attribute Generator Inject
|
@Moe-Baker This is really impressive, 1.36/1.87 = 0.72%, so almost 30% faster. I wonder if we could achieve similar results by "baking" the reflection without using source generators, like for instance using |
|
From my experience, Delegate.CreateDelegate & Expression Trees will give similar performance, but have harsher limitations, as they both wont work with AOT compilation, so no IL2CPP. |
|
Any update @gustavopsantos ? Also 1 suggestion is to change IAttributeInjectionContract's name because it might be useful for people who want to implement custom injection method |
|
Also, the pdb file is missing it's meta file. Which throws an error when installing through UPM |
Description
Implemented a source generator to supplement AttributeInjector's reflection usage, while maintaining the old reflection API for the time being, but I'm open to removing it and updating the PR if needed.
The source generator is implemented as a Roslyn source generator, all in accordance with the Unity documentation for Unity 2021.3.
The source generator is fully linked with the Unity project and is working as expected.
The motivation was to improve the performance of Reflex's Inject functionality, which relies entirely on reflection.
The source-generated injection system works in a rather simple way; it will look for a
IAttributeInjectionContractinterface on the type being injected to, if that interface exists, the method inside the interface is invoked, if not, the old reflection-based system is run.The source generator's job is to automatically implement that interface and populate its method call; it accomplishes this by looking for any type that is decorated with the
[SourceGeneratorInjectable]attribute, wherein the decorated needs to be:Custom diagnostics were also implemented for:
[SourceGeneratorInjectable]must be partial alongside their containing types.[SourceGeneratorInjectable]must be public alongside their containing types.[Inject]must have a setter.[Inject]should return void.[Inject]must not be readonly.The addition of the source generator was accomplished by creating a new C# solution "Reflex.Generator", the solution has 3 projects, the generator project, a mock project & a tests project.
The generator (Reflex.Generator.Injector) comes with two publish profiles, one of them (Send to Unity) will publish the generator and send it to the appropriate directory within the Unity project.
The generator should be sent to Unity whenever a code change is done within it; the publish profile will handle this entire operation, just needs to be called from VS/Rider.
No new dependencies are required.
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
SourceGeneratedInjectorTests.Ran all Unity tests after implementing the feature, 4 failed, swapped to main branch to test without my changes, same 4 tests failed, I'm not sure why, but it doesn't seem to be related to my changes.
Test Configuration:
Checklist: