Skip to content

Commit

Permalink
Improved unique tag name
Browse files Browse the repository at this point in the history
NikolayPianikov committed Mar 18, 2024
1 parent 25f7926 commit 537d9b1
Showing 12 changed files with 126 additions and 110 deletions.
16 changes: 8 additions & 8 deletions readme/tag-unique.md
Original file line number Diff line number Diff line change
@@ -46,11 +46,11 @@ classDiagram
+ object Resolve(Type type, object? tag)
}
class IEnumerableᐸIDependencyᐸStringᐳᐳ
AbcDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : cf28a5f5-c0c6-4d80-9869-561448e661e1
AbcDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : Unique tag 1
class AbcDependencyᐸStringᐳ {
+AbcDependency()
}
XyzDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : 0c31c79e-0327-4b14-9fc1-166a5a5aa440
XyzDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : Unique tag 2
class XyzDependencyᐸStringᐳ {
+XyzDependency()
}
@@ -64,8 +64,8 @@ classDiagram
class IServiceᐸStringᐳ {
<<abstract>>
}
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- AbcDependencyᐸStringᐳ : cf28a5f5-c0c6-4d80-9869-561448e661e1 IDependencyᐸStringᐳ
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- XyzDependencyᐸStringᐳ : 0c31c79e-0327-4b14-9fc1-166a5a5aa440 IDependencyᐸStringᐳ
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- AbcDependencyᐸStringᐳ : Unique tag 1 IDependencyᐸStringᐳ
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- XyzDependencyᐸStringᐳ : Unique tag 2 IDependencyᐸStringᐳ
Composition ..> ServiceᐸStringᐳ : IServiceᐸStringᐳ Root
ServiceᐸStringᐳ o-- "PerBlock" IEnumerableᐸIDependencyᐸStringᐳᐳ : IEnumerableᐸIDependencyᐸStringᐳᐳ
```
@@ -157,11 +157,11 @@ partial class Composition
" + object Resolve(Type type, object? tag)\n" +
" }\n" +
" class IEnumerableᐸIDependencyᐸStringᐳᐳ\n" +
" AbcDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : cf28a5f5-c0c6-4d80-9869-561448e661e1 \n" +
" AbcDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : Unique tag 1 \n" +
" class AbcDependencyᐸStringᐳ {\n" +
" +AbcDependency()\n" +
" }\n" +
" XyzDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : 0c31c79e-0327-4b14-9fc1-166a5a5aa440 \n" +
" XyzDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : Unique tag 2 \n" +
" class XyzDependencyᐸStringᐳ {\n" +
" +XyzDependency()\n" +
" }\n" +
@@ -175,8 +175,8 @@ partial class Composition
" class IServiceᐸStringᐳ {\n" +
" <<abstract>>\n" +
" }\n" +
" IEnumerableᐸIDependencyᐸStringᐳᐳ *-- AbcDependencyᐸStringᐳ : cf28a5f5-c0c6-4d80-9869-561448e661e1 IDependencyᐸStringᐳ\n" +
" IEnumerableᐸIDependencyᐸStringᐳᐳ *-- XyzDependencyᐸStringᐳ : 0c31c79e-0327-4b14-9fc1-166a5a5aa440 IDependencyᐸStringᐳ\n" +
" IEnumerableᐸIDependencyᐸStringᐳᐳ *-- AbcDependencyᐸStringᐳ : Unique tag 1 IDependencyᐸStringᐳ\n" +
" IEnumerableᐸIDependencyᐸStringᐳᐳ *-- XyzDependencyᐸStringᐳ : Unique tag 2 IDependencyᐸStringᐳ\n" +
" Composition ..> ServiceᐸStringᐳ : IServiceᐸStringᐳ Root\n" +
" ServiceᐸStringᐳ o-- \"PerBlock\" IEnumerableᐸIDependencyᐸStringᐳᐳ : IEnumerableᐸIDependencyᐸStringᐳᐳ";
}
107 changes: 51 additions & 56 deletions readme/tracking-disposable-instances-per-a-composition-root.md
Original file line number Diff line number Diff line change
@@ -25,20 +25,6 @@ class Service(IDependency dependency) : IService
public IDependency Dependency { get; } = dependency;
}

readonly struct Owned<T>(
T value,
List<IDisposable> disposables)
: IDisposable
{
public T Value { get; } = value;

public void Dispose()
{
disposables.Reverse();
disposables.ForEach(i => i.Dispose());
}
}

partial class Composition
{
private List<IDisposable> _disposables = [];
@@ -49,39 +35,42 @@ partial class Composition
// when an instance is created
.Hint(Hint.OnNewInstance, "On")

// Specifies to call the partial method OnNewInstance
// Specifies to call the partial method
// only for instances with lifetime
// Transient, PerResolve and PerBlock
.Hint(
Hint.OnNewInstanceLifetimeRegularExpression,
.Hint(Hint.OnNewInstanceLifetimeRegularExpression,
"Transient|PerResolve|PerBlock")

// Specifies to call the partial method OnNewInstance
// for instances other than Composition.Owned<T>
.Hint(
Hint.OnNewInstanceImplementationTypeNameRegularExpression,
"^((?!Owned<).)*$")

.Bind().To(ctx =>
{
ctx.Inject(out TT value);
var disposables = _disposables;
_disposables = [];
return new Owned<TT>(value, disposables);
})

.Bind<IDependency>().To<Dependency>()
.Bind<IService>().To<Service>()
.Root<Owned<IService>>("Root");

partial void OnNewInstance<T>(
ref T value,
object? tag,
Lifetime lifetime)
partial void OnNewInstance<T>(ref T value, object? tag, Lifetime lifetime)
{
if (value is not IDisposable disposable) return;
if (value is IOwned || value is not IDisposable disposable) return;
_disposables.Add(disposable);
}

public interface IOwned;

public readonly struct Owned<T>: IDisposable, IOwned
{
public readonly T Value;
private readonly List<IDisposable> _disposable;

public Owned(T value, Composition composition)
{
Value = value;
_disposable = composition._disposables;
composition._disposables = [];
}

public void Dispose()
{
_disposable.Reverse();
_disposable.ForEach(i => i.Dispose());
}
}
}

var composition = new Composition();
@@ -118,6 +107,10 @@ classDiagram
+ object Resolve(Type type)
+ object Resolve(Type type, object? tag)
}
class Composition
class OwnedᐸIServiceᐳ {
+Owned(IService value, Composition composition)
}
Dependency --|> IDependency :
class Dependency {
+Dependency()
@@ -132,9 +125,10 @@ classDiagram
class IService {
<<abstract>>
}
OwnedᐸIServiceᐳ *-- Service : IService
OwnedᐸIServiceᐳ *-- Composition : Composition
Service *-- Dependency : IDependency
Composition ..> OwnedᐸIServiceᐳ : OwnedᐸIServiceᐳ Root
OwnedᐸIServiceᐳ *-- Service : IService
```

</details>
@@ -157,21 +151,17 @@ partial class Composition
_rootM03D18di = baseComposition._rootM03D18di;
}

public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> Root
public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> Root
{
get
{
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency transientM03D18di2_Dependency = new Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency();
OnNewInstance<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency>(ref transientM03D18di2_Dependency, null, Pure.DI.Lifetime.Transient);
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Service transientM03D18di1_Service = new Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Service(transientM03D18di2_Dependency);
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency transientM03D18di3_Dependency = new Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency();
OnNewInstance<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Dependency>(ref transientM03D18di3_Dependency, null, Pure.DI.Lifetime.Transient);
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition transientM03D18di2_Composition = this;
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Service transientM03D18di1_Service = new Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Service(transientM03D18di3_Dependency);
OnNewInstance<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Service>(ref transientM03D18di1_Service, null, Pure.DI.Lifetime.Transient);
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> transientM03D18di0_Owned;
{
var value_M03D18di1 = transientM03D18di1_Service;
var disposables_M03D18di2 = _disposables;
_disposables = [];
transientM03D18di0_Owned = new Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>(value_M03D18di1, disposables_M03D18di2);
}
Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> transientM03D18di0_Owned = new Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>(transientM03D18di1_Service, transientM03D18di2_Composition);
OnNewInstance<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>>(ref transientM03D18di0_Owned, null, Pure.DI.Lifetime.Transient);
return transientM03D18di0_Owned;
}
}
@@ -229,6 +219,10 @@ partial class Composition
" + object Resolve(Type type)\n" +
" + object Resolve(Type type, object? tag)\n" +
" }\n" +
" class Composition\n" +
" class OwnedᐸIServiceᐳ {\n" +
" +Owned(IService value, Composition composition)\n" +
" }\n" +
" Dependency --|> IDependency : \n" +
" class Dependency {\n" +
" +Dependency()\n" +
@@ -243,9 +237,10 @@ partial class Composition
" class IService {\n" +
" <<abstract>>\n" +
" }\n" +
" OwnedᐸIServiceᐳ *-- Service : IService\n" +
" OwnedᐸIServiceᐳ *-- Composition : Composition\n" +
" Service *-- Dependency : IDependency\n" +
" Composition ..> OwnedᐸIServiceᐳ : OwnedᐸIServiceᐳ Root\n" +
" OwnedᐸIServiceᐳ *-- Service : IService";
" Composition ..> OwnedᐸIServiceᐳ : OwnedᐸIServiceᐳ Root";
}

private readonly static int _bucketSizeM03D18di;
@@ -254,13 +249,13 @@ partial class Composition
static Composition()
{
var valResolverM03D18di_0000 = new ResolverM03D18di_0000();
ResolverM03D18di<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>>.Value = valResolverM03D18di_0000;
ResolverM03D18di<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>>.Value = valResolverM03D18di_0000;
_bucketsM03D18di = global::Pure.DI.Buckets<global::System.Type, global::Pure.DI.IResolver<Composition, object>>.Create(
1,
out _bucketSizeM03D18di,
new global::Pure.DI.Pair<global::System.Type, global::Pure.DI.IResolver<Composition, object>>[1]
{
new global::Pure.DI.Pair<global::System.Type, global::Pure.DI.IResolver<Composition, object>>(typeof(Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>), valResolverM03D18di_0000)
new global::Pure.DI.Pair<global::System.Type, global::Pure.DI.IResolver<Composition, object>>(typeof(Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>), valResolverM03D18di_0000)
});
}

@@ -279,21 +274,21 @@ partial class Composition
}
}

private sealed class ResolverM03D18di_0000: global::Pure.DI.IResolver<Composition, Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>>, global::Pure.DI.IResolver<Composition, object>
private sealed class ResolverM03D18di_0000: global::Pure.DI.IResolver<Composition, Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>>, global::Pure.DI.IResolver<Composition, object>
{
public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> Resolve(Composition composition)
public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> Resolve(Composition composition)
{
return composition.Root;
}

public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> ResolveByTag(Composition composition, object tag)
public Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService> ResolveByTag(Composition composition, object tag)
{
switch (tag)
{
case null:
return composition.Root;
}
throw new global::System.InvalidOperationException($"Cannot resolve composition root \"{tag}\" of type Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>.");
throw new global::System.InvalidOperationException($"Cannot resolve composition root \"{tag}\" of type Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.Composition.Owned<Pure.DI.UsageTests.Hints.TrackingDisposableInstancesPerRootScenario.IService>.");
}
object global::Pure.DI.IResolver<Composition, object>.Resolve(Composition composition)
{
6 changes: 4 additions & 2 deletions src/Pure.DI.Core/Core/BindingBuilder.cs
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@
namespace Pure.DI.Core;

internal class BindingBuilder(
[Tag("UniqueTags")] IIdGenerator idGenerator,
IBaseSymbolsProvider baseSymbolsProvider)
: IBindingBuilder
{
private MdDefaultLifetime? _defaultLifetime;
private SemanticModel? _semanticModel;
@@ -138,7 +140,7 @@ public MdBinding Build(MdSetup setup)
}
}

private static MdTag BuildTag(MdTag tag, ITypeSymbol? type)
private MdTag BuildTag(MdTag tag, ITypeSymbol? type)
{
if (type is null || tag.Value is null)
{
@@ -154,7 +156,7 @@ private static MdTag BuildTag(MdTag tag, ITypeSymbol? type)
return tag with { Value = type };

case Tag.Unique:
return tag with { Value = Guid.NewGuid() };
return tag with { Value = new UniqueTag(idGenerator.Generate()) };
}
}

2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Code/BuildTools.cs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ public void AddPureHeader(LinesBuilder code)
code.AppendLine("#endif");
}

public string GetDeclaration(Variable variable, bool typeIsRequired = false) =>
public string GetDeclaration(Variable variable) =>
variable.IsDeclared ? "" : $"{typeResolver.Resolve(variable.InstanceType)} ";

public string OnInjected(BuildContext ctx, Variable variable)
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Code/ConstructCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -102,7 +102,7 @@ private static void BuildSpan(BuildContext ctx, in DpConstruct span)
&& span.Binding.SemanticModel.Compilation.GetLanguageVersion() >= LanguageVersion.CSharp7_3;

var createInstance = isStackalloc ? $"stackalloc {createArray}" : $"new {Names.SystemNamespace}Span<{span.Source.ElementType}>(new {createArray})";
ctx.Code.AppendLine($"{ctx.BuildTools.GetDeclaration(variable, isStackalloc)}{variable.VariableName} = {createInstance};");
ctx.Code.AppendLine($"{ctx.BuildTools.GetDeclaration(variable)}{variable.VariableName} = {createInstance};");
ctx.Code.AppendLines(ctx.BuildTools.OnCreated(ctx, variable));
}

4 changes: 2 additions & 2 deletions src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -32,13 +32,13 @@ public void Build(BuildContext ctx, in DpFactory factory)
SyntaxNode syntaxNode = lambda.Block is not null ? lambda.Block : SyntaxFactory.ExpressionStatement((ExpressionSyntax)lambda.Body);
if (syntaxNode is not BlockSyntax)
{
code.Append($"{ctx.BuildTools.GetDeclaration(variable, true)}{variable.VariableName} = ");
code.Append($"{ctx.BuildTools.GetDeclaration(variable)}{variable.VariableName} = ");
}
else
{
if (!variable.IsDeclared)
{
code.AppendLine($"{ctx.BuildTools.GetDeclaration(variable, true)}{variable.VariableName};");
code.AppendLine($"{ctx.BuildTools.GetDeclaration(variable)}{variable.VariableName};");
}
}

2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Code/IBuildTools.cs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ internal interface IBuildTools
{
void AddPureHeader(LinesBuilder code);

string GetDeclaration(Variable variable, bool typeIsRequired = false);
string GetDeclaration(Variable variable);

string OnInjected(BuildContext ctx, Variable variable);

20 changes: 20 additions & 0 deletions src/Pure.DI.Core/Core/IBindingBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Pure.DI.Core;

internal interface IBindingBuilder
{
MdDefaultLifetime DefaultLifetime { set; }

MdLifetime Lifetime { set; }

MdImplementation Implementation { set; }

MdFactory Factory { set; }

MdArg Arg { set; }

void AddContract(in MdContract contract);

void AddTag(in MdTag tag);

MdBinding Build(MdSetup setup);
}
6 changes: 3 additions & 3 deletions src/Pure.DI.Core/Core/SetupsBuilder.cs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ namespace Pure.DI.Core;
internal sealed class SetupsBuilder(
Func<IMetadataSyntaxWalker> metadataSyntaxWalkerFactory,
ICache<ImmutableArray<byte>, bool> setupCache,
IBaseSymbolsProvider baseSymbolsProvider)
Func<IBindingBuilder> bindingBuilderFactory)
: IBuilder<SyntaxUpdate, IEnumerable<MdSetup>>, IMetadataVisitor
{
private readonly List<MdSetup> _setups = [];
@@ -15,7 +15,7 @@ internal sealed class SetupsBuilder(
private readonly List<MdTagAttribute> _tagAttributes = [];
private readonly List<MdOrdinalAttribute> _ordinalAttributes = [];
private readonly List<MdUsingDirectives> _usingDirectives = [];
private BindingBuilder _bindingBuilder = new(baseSymbolsProvider);
private IBindingBuilder _bindingBuilder = bindingBuilderFactory();
private MdSetup? _setup;

public IEnumerable<MdSetup> Build(SyntaxUpdate update)
@@ -127,6 +127,6 @@ setup with
_ordinalAttributes.Clear();
_usingDirectives.Clear();
_setup = default;
_bindingBuilder = new BindingBuilder(baseSymbolsProvider);
_bindingBuilder = bindingBuilderFactory();
}
}
8 changes: 8 additions & 0 deletions src/Pure.DI.Core/Core/UniqueTag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// ReSharper disable NotAccessedPositionalProperty.Global
namespace Pure.DI.Core;

internal record UniqueTag(int Id)
{
public override string ToString() =>
$"Unique tag {Id}";
}
2 changes: 2 additions & 0 deletions src/Pure.DI.Core/Generator.Composition.cs
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ private static void Setup() => DI.Setup(nameof(Generator))
.Bind().To<DependencyGraphBuilder>()
.Bind().To<TypeConstructor>()
.Bind<IEqualityComparer<string>>().To(_ => StringComparer.InvariantCultureIgnoreCase)
.Bind().To<BindingBuilder>()

// Singleton
.DefaultLifetime(Singleton)
@@ -118,5 +119,6 @@ private static void Setup() => DI.Setup(nameof(Generator))
.Bind().To<TypeResolver>()
.Bind().To<LogObserver>()
.Bind().To<Filter>()
.Bind("UniqueTags").To<IdGenerator>()
.Bind().To<IdGenerator>();
}
Original file line number Diff line number Diff line change
@@ -35,20 +35,6 @@ class Service(IDependency dependency) : IService
public IDependency Dependency { get; } = dependency;
}

readonly struct Owned<T>(
T value,
List<IDisposable> disposables)
: IDisposable
{
public T Value { get; } = value;

public void Dispose()
{
disposables.Reverse();
disposables.ForEach(i => i.Dispose());
}
}

partial class Composition
{
private List<IDisposable> _disposables = [];
@@ -59,39 +45,42 @@ private void Setup() =>
// when an instance is created
.Hint(Hint.OnNewInstance, "On")

// Specifies to call the partial method OnNewInstance
// Specifies to call the partial method
// only for instances with lifetime
// Transient, PerResolve and PerBlock
.Hint(
Hint.OnNewInstanceLifetimeRegularExpression,
.Hint(Hint.OnNewInstanceLifetimeRegularExpression,
"Transient|PerResolve|PerBlock")

// Specifies to call the partial method OnNewInstance
// for instances other than Composition.Owned<T>
.Hint(
Hint.OnNewInstanceImplementationTypeNameRegularExpression,
"^((?!Owned<).)*$")

.Bind().To(ctx =>
{
ctx.Inject(ctx.Tag, out TT value);
var disposables = _disposables;
_disposables = [];
return new Owned<TT>(value, disposables);
})

.Bind<IDependency>().To<Dependency>()
.Bind<IService>().To<Service>()
.Root<Owned<IService>>("Root");

partial void OnNewInstance<T>(
ref T value,
object? tag,
Lifetime lifetime)
partial void OnNewInstance<T>(ref T value, object? tag, Lifetime lifetime)
{
if (value is not IDisposable disposable) return;
if (value is IOwned || value is not IDisposable disposable) return;
_disposables.Add(disposable);
}

public interface IOwned;

public readonly struct Owned<T>: IDisposable, IOwned
{
public readonly T Value;
private readonly List<IDisposable> _disposable;

public Owned(T value, Composition composition)
{
Value = value;
_disposable = composition._disposables;
composition._disposables = [];
}

public void Dispose()
{
_disposable.Reverse();
_disposable.ForEach(i => i.Dispose());
}
}
}
// }

0 comments on commit 537d9b1

Please sign in to comment.