Skip to content

Commit 790feca

Browse files
#138 Make anonymous roots lightweight
1 parent 535dfd7 commit 790feca

15 files changed

Lines changed: 114 additions & 56 deletions

src/Pure.DI.Core/Core/Code/Accumulators.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public IEnumerable<Accumulator> CreateAccumulators(
5252
Root root,
5353
IEnumerable<(MdAccumulator accumulator, Dependency dependency)> accumulators,
5454
IVarsMap varsMap) =>
55-
accumulators.Select(i => new Accumulator(varsMap.GetInjection(graph, root, i.dependency.Injection, i.dependency.Source), i.accumulator.Type, i.accumulator.Lifetime));
55+
accumulators.Select(i => new Accumulator(varsMap.GetInjection(graph, i.dependency.Injection, i.dependency.Source), i.accumulator.Type, i.accumulator.Lifetime));
5656

5757
public void BuildAccumulators(CodeContext ctx)
5858
{

src/Pure.DI.Core/Core/Code/ArrayCodeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public IEnumerator Build(CodeBuilderContext data)
2323
// ReSharper disable once LoopCanBeConvertedToQuery
2424
foreach (var dependency in arrayDependencies)
2525
{
26-
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, ctx.RootContext.Root, dependency.Injection, dependency.Source));
26+
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, dependency.Injection, dependency.Source));
2727
}
2828

2929
injections.Sort(variableTools.InjectionComparer);

src/Pure.DI.Core/Core/Code/CompositionBuilder.cs

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class CompositionBuilder(
1010
IBuilder<CompositionCode, Lines> classDiagramBuilder,
1111
IOverridesRegistry overridesRegistry,
1212
IRegistry<int> bindingsRegistry,
13+
IGraphWalker<RootArgsContext, ImmutableArray<Dependency>> graphWalker,
14+
IGraphVisitor<RootArgsContext, ImmutableArray<Dependency>> rootArgsVisitor,
1315
CancellationToken cancellationToken)
1416
: IBuilder<DependencyGraph, CompositionCode>
1517
{
@@ -27,68 +29,81 @@ public CompositionCode Build(DependencyGraph graph)
2729
break;
2830
}
2931

32+
var typeDescription = typeResolver.Resolve(graph.Source, root.Injection.Type);
33+
var processedRoot = root with { TypeDescription = typeDescription };
34+
if (typeDescription.TypeArgs.Count > 0)
35+
{
36+
processedRoot = processedRoot with { Kind = processedRoot.Kind & ~RootKinds.Light };
37+
}
38+
39+
IEnumerable<VarDeclaration> args;
3040
var lines = new Lines();
3141
using var rootToken = varsMap.Root(lines);
32-
var ctx = new RootContext(graph, root, varsMap, lines);
33-
var rootVarInjection = rootBuilder().Build(ctx);
34-
var isThreadSafeRoot = ctx.LockIsInUse || graph.Source.Hints.IsThreadSafeEnabled && varsMap.IsThreadSafe;
35-
if (root.IsStatic)
42+
if (root.Source.Kind.HasFlag(RootKinds.Light) && typeDescription.TypeArgs.Count == 0)
3643
{
37-
if (isThreadSafeRoot || overridesRegistry.GetOverrides(root).Any())
38-
{
39-
// resolveLock local field
40-
var newLines = new Lines();
41-
newLines.AppendLine(new Line(int.MinValue, "#if NET9_0_OR_GREATER"));
42-
newLines.AppendLine($"var {Names.PerResolveLockFieldName} = new {Names.LockTypeName}();");
43-
newLines.AppendLine(new Line(int.MinValue, "#else"));
44-
newLines.AppendLine($"var {Names.PerResolveLockFieldName} = new {Names.ObjectTypeName}();");
45-
newLines.AppendLine(new Line(int.MinValue, "#endif"));
46-
newLines.AppendLines(ctx.Lines);
47-
lines = newLines;
48-
ctx = ctx with { Lines = lines };
49-
}
44+
var rootArgsContext = new RootArgsContext(varsMap, new List<VarDeclaration>());
45+
graphWalker.Walk(rootArgsContext, graph, root.Node, rootArgsVisitor, cancellationToken);
46+
args = rootArgsContext.Args;
5047
}
5148
else
5249
{
53-
isThreadSafe |= isThreadSafeRoot;
54-
}
50+
var ctx = new RootContext(graph, root, varsMap, lines);
51+
var rootVarInjection = rootBuilder().Build(ctx);
52+
var isThreadSafeRoot = ctx.LockIsInUse || graph.Source.Hints.IsThreadSafeEnabled && varsMap.IsThreadSafe;
53+
if (root.IsStatic)
54+
{
55+
if (isThreadSafeRoot || overridesRegistry.GetOverrides(root).Any())
56+
{
57+
// resolveLock local field
58+
var newLines = new Lines();
59+
newLines.AppendLine(new Line(int.MinValue, "#if NET9_0_OR_GREATER"));
60+
newLines.AppendLine($"var {Names.PerResolveLockFieldName} = new {Names.LockTypeName}();");
61+
newLines.AppendLine(new Line(int.MinValue, "#else"));
62+
newLines.AppendLine($"var {Names.PerResolveLockFieldName} = new {Names.ObjectTypeName}();");
63+
newLines.AppendLine(new Line(int.MinValue, "#endif"));
64+
newLines.AppendLines(ctx.Lines);
65+
lines = newLines;
66+
ctx = ctx with { Lines = lines };
67+
}
68+
}
69+
else
70+
{
71+
isThreadSafe |= isThreadSafeRoot;
72+
}
5573

56-
lines.AppendLine($"return {rootVarInjection.Var.CodeExpression};");
57-
foreach (var localFunction in varsMap.Vars.Select(i => i.LocalFunction).Where(i => i.Count > 0))
58-
{
59-
lines.AppendLine();
60-
lines.AppendLines(localFunction);
74+
lines.AppendLine($"return {rootVarInjection.Var.CodeExpression};");
75+
foreach (var localFunction in varsMap.Vars.Select(i => i.LocalFunction).Where(i => i.Count > 0))
76+
{
77+
lines.AppendLine();
78+
lines.AppendLines(localFunction);
79+
}
80+
81+
processedRoot = processedRoot with { Lines = ctx.Lines };
82+
args = varsMap.Declarations.Where(i => i.Node.Arg is not null);
6183
}
6284

63-
var args = varDeclarationTools.Sort(varsMap.Declarations.Where(i => i.Node.Arg is not null)).ToList();
64-
var rootArgs = args.GetArgsOfKind(ArgKind.Root);
65-
var processedRoot = root with
66-
{
67-
Lines = ctx.Lines,
68-
TypeDescription = typeResolver.Resolve(graph.Source, root.Injection.Type),
69-
RootArgs = rootArgs.ToImmutableArray()
70-
};
85+
var currentArgs = varDeclarationTools.Sort(args).ToList();
86+
87+
var currentClassArgs = currentArgs.GetArgsOfKind(ArgKind.Composition)
88+
.Where(arg => arg.Node.Arg is not { Source.IsSetupContext: true })
89+
.Where(arg => bindingsRegistry.IsRegistered(graph.Source, arg.Node.BindingId));
90+
91+
classArgs.AddRange(currentClassArgs);
92+
93+
var currentRootArgs = currentArgs.GetArgsOfKind(ArgKind.Root).ToImmutableArray();
7194

72-
classArgs.AddRange(args.GetArgsOfKind(ArgKind.Composition)
73-
.Where(node => node.Node.Arg is not { Source.IsSetupContext: true })
74-
.Where(node => bindingsRegistry.IsRegistered(graph.Source, node.Node.BindingId)));
75-
var typeDescription = typeResolver.Resolve(graph.Source, processedRoot.Injection.Type);
7695
var isMethod = processedRoot.Source.IsBuilder
7796
|| (processedRoot.Kind & RootKinds.Method) == RootKinds.Method
78-
|| processedRoot.RootArgs.Length > 0
97+
|| currentRootArgs.Length > 0
7998
|| typeDescription.TypeArgs.Count > 0;
8099

81100
processedRoot = processedRoot with
82101
{
83-
TypeDescription = typeDescription,
102+
RootArgs = currentRootArgs.ToImmutableArray(),
84103
IsMethod = isMethod
104+
// , Kind = processedRoot.Kind & ~RootKinds.Light
85105
};
86106

87-
if (processedRoot.Kind.HasFlag(RootKinds.Light) && typeDescription.TypeArgs.Count > 0)
88-
{
89-
processedRoot = processedRoot with { Kind = processedRoot.Kind & ~RootKinds.Light };
90-
}
91-
92107
roots.Add(processedRoot);
93108
}
94109

src/Pure.DI.Core/Core/Code/EnumerableCodeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public IEnumerator Build(CodeBuilderContext data)
3636
// ReSharper disable once LoopCanBeConvertedToQuery
3737
foreach (var dependency in enumerableDependencies)
3838
{
39-
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, ctx.RootContext.Root, dependency.Injection, dependency.Source));
39+
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, dependency.Injection, dependency.Source));
4040
}
4141

4242
injections.Sort(variableTools.InjectionComparer);

src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ public IEnumerator Build(CodeBuilderContext data)
243243
{
244244
foreach (var dependency in dependencies)
245245
{
246-
var dependencyVar = varsMap.GetInjection(ctx.RootContext.Graph, ctx.RootContext.Root, dependency.Injection, dependency.Source);
246+
var dependencyVar = varsMap.GetInjection(ctx.RootContext.Graph, dependency.Injection, dependency.Source);
247247
varInjections.Add(dependencyVar);
248248
if (dependencyVar.Injection.Kind is InjectionKind.FactoryInjection)
249249
{

src/Pure.DI.Core/Core/Code/IVarsMap.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ interface IVarsMap
2424
/// Gets a variable injection for the specified node.
2525
/// </summary>
2626
/// <param name="graph">The dependency graph.</param>
27-
/// <param name="root">The composition root.</param>
2827
/// <param name="injection">The injection information.</param>
2928
/// <param name="node">The dependency node.</param>
3029
/// <returns>The variable injection.</returns>
31-
VarInjection GetInjection(DependencyGraph graph, Root root, in Injection injection, IDependencyNode node);
30+
VarInjection GetInjection(DependencyGraph graph, in Injection injection, IDependencyNode node);
3231

3332
/// <summary>
3433
/// Resets the map to the root state.

src/Pure.DI.Core/Core/Code/ImplementationCodeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public IEnumerator Build(CodeBuilderContext data)
2929
// ReSharper disable once LoopCanBeConvertedToQuery
3030
foreach (var dependency in implementationDependencies)
3131
{
32-
injectionsList.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, ctx.RootContext.Root, dependency.Injection, dependency.Source));
32+
injectionsList.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, dependency.Injection, dependency.Source));
3333
}
3434

3535
injectionsList.Sort(variableTools.InjectionComparer);

src/Pure.DI.Core/Core/Code/RootBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class RootBuilder(
2121
public VarInjection Build(in RootContext rootContext)
2222
{
2323
var rootVarsMap = rootContext.VarsMap;
24-
var rootVarInjection = rootVarsMap.GetInjection(rootContext.Graph, rootContext.Root, rootContext.Root.Injection, rootContext.Root.Node);
24+
var rootVarInjection = rootVarsMap.GetInjection(rootContext.Graph, rootContext.Root.Injection, rootContext.Root.Node);
2525
var lines = new Lines();
2626
var ctx = new CodeContext(
2727
rootContext,

src/Pure.DI.Core/Core/Code/SpanCodeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public IEnumerator Build(CodeBuilderContext data)
2525
var injections = new List<VarInjection>(spanDependencies.Count);
2626
foreach (var dependency in spanDependencies)
2727
{
28-
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, ctx.RootContext.Root, dependency.Injection, dependency.Source));
28+
injections.Add(ctx.VarsMap.GetInjection(ctx.RootContext.Graph, dependency.Injection, dependency.Source));
2929
}
3030

3131
injections.Sort(variableTools.InjectionComparer);

src/Pure.DI.Core/Core/Code/VarsMap.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class VarsMap(
2323
public bool IsThreadSafe { get; private set; }
2424

2525
/// <inheritdoc />
26-
public VarInjection GetInjection(DependencyGraph graph, Root root, in Injection injection, IDependencyNode node)
26+
public VarInjection GetInjection(DependencyGraph graph, in Injection injection, IDependencyNode node)
2727
{
2828
VarInjection varInjection;
2929
var trace = new StringBuilder();

0 commit comments

Comments
 (0)