From 2ceac63e14f23843cf2b61e4dba20a963333bb81 Mon Sep 17 00:00:00 2001 From: Nikolay Pianikov Date: Mon, 16 Dec 2024 21:57:15 +0300 Subject: [PATCH] Update README.md --- readme/async-disposable-scope.md | 4 +- readme/async-root.md | 20 ++-- readme/auto-scoped.md | 10 +- readme/bind-attribute-for-a-generic-type.md | 4 +- .../bind-attribute-with-lifetime-and-tag.md | 4 +- readme/bind-attribute.md | 4 +- .../build-up-of-an-existing-generic-object.md | 8 +- readme/build-up-of-an-existing-object.md | 8 +- readme/di-tracing-via-serilog.md | 100 +++++------------- readme/exposed-generic-roots-with-args.md | 6 +- readme/exposed-generic-roots.md | 4 +- readme/exposed-roots-via-arg.md | 4 +- readme/exposed-roots-via-root-arg.md | 4 +- readme/exposed-roots-with-tags.md | 4 +- readme/exposed-roots.md | 4 +- readme/factory.md | 10 +- readme/func-with-arguments.md | 4 +- readme/func-with-tag.md | 4 +- readme/func.md | 4 +- ...sync-composition-roots-with-constraints.md | 44 ++++---- ...eric-composition-roots-with-constraints.md | 4 +- readme/generic-composition-roots.md | 4 +- readme/lazy.md | 8 +- readme/manually-started-tasks.md | 10 +- readme/scope.md | 4 +- readme/serilog.md | 84 ++++----------- readme/simplified-factory.md | 8 +- readme/task.md | 20 ++-- readme/threadsafe-hint.md | 4 +- ...async-disposable-instances-in-delegates.md | 14 +-- ...osable-instances-per-a-composition-root.md | 10 +- ...cking-disposable-instances-in-delegates.md | 14 +-- ...osable-instances-per-a-composition-root.md | 10 +- ...sable-instances-using-pre-built-classes.md | 20 ++-- ...able-instances-with-different-lifetimes.md | 28 ++--- readme/valuetask.md | 4 +- src/Pure.DI.Core/Components/Api.g.cs | 12 ++- src/Pure.DI.Core/Core/Code/BuildContext.cs | 1 + .../Core/Code/CompositionBuilder.cs | 1 + .../Core/Code/FactoryCodeBuilder.cs | 2 +- src/Pure.DI.Core/Core/Code/FactoryRewriter.cs | 19 +++- .../Core/Code/StatementCodeBuilder.cs | 15 ++- src/Pure.DI.Core/Core/Code/Variable.cs | 1 + .../Core/Code/VariablesBuilder.cs | 9 +- .../Pure.DI.IntegrationTests/FactoryTests.cs | 83 +++++++++++++++ .../Advanced/DITracingViaSerilogScenario.cs | 23 ++-- .../Advanced/SerilogScenario.cs | 23 ++-- 47 files changed, 354 insertions(+), 335 deletions(-) diff --git a/readme/async-disposable-scope.md b/readme/async-disposable-scope.md index 964d0fc1b..4e58cbda6 100644 --- a/readme/async-disposable-scope.md +++ b/readme/async-disposable-scope.md @@ -139,8 +139,8 @@ partial class Composition: IDisposable, IAsyncDisposable Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { Composition transientComposition3 = this; - Session localValue85 = new Session(transientComposition3); - return localValue85; + Session localValue89 = new Session(transientComposition3); + return localValue89; }); return new Program(perBlockFunc1); } diff --git a/readme/async-root.md b/readme/async-root.md index e57e170a5..6f564c66a 100644 --- a/readme/async-root.md +++ b/readme/async-root.md @@ -51,26 +51,26 @@ partial class Composition public Task GetMyServiceAsync(CancellationToken cancellationToken) { TaskFactory perBlockTaskFactory2; - CancellationToken localCancellationToken35 = cancellationToken; + CancellationToken localCancellationToken39 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions36 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions40 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions37 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions41 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler38 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory(localCancellationToken35, localTaskCreationOptions36, localTaskContinuationOptions37, localTaskScheduler38); + TaskScheduler localTaskScheduler42 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory(localCancellationToken39, localTaskCreationOptions40, localTaskContinuationOptions41, localTaskScheduler42); Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IService localValue39 = new Service(new Dependency()); - return localValue39; + IService localValue43 = new Service(new Dependency()); + return localValue43; }); Task transientTask0; // Injects an instance factory - Func localFactory40 = perBlockFunc1; + Func localFactory44 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory localTaskFactory41 = perBlockTaskFactory2; + TaskFactory localTaskFactory45 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory41.StartNew(localFactory40); + transientTask0 = localTaskFactory45.StartNew(localFactory44); return transientTask0; } } diff --git a/readme/auto-scoped.md b/readme/auto-scoped.md index 052b2eb9f..c754ff1b6 100644 --- a/readme/auto-scoped.md +++ b/readme/auto-scoped.md @@ -96,13 +96,13 @@ partial class Composition { Composition transientComposition3 = this; IService transientIService2; - Composition localBaseComposition87 = transientComposition3; + Composition localBaseComposition91 = transientComposition3; // Creates a session - var localSession88= new Composition(localBaseComposition87); + var localSession92= new Composition(localBaseComposition91); // Provides a root - transientIService2 = localSession88.SessionRoot; - IService localValue86 = transientIService2; - return localValue86; + transientIService2 = localSession92.SessionRoot; + IService localValue90 = transientIService2; + return localValue90; }); return new Program(perBlockFunc1); } diff --git a/readme/bind-attribute-for-a-generic-type.md b/readme/bind-attribute-for-a-generic-type.md index 69ef03fb6..0a64cb699 100644 --- a/readme/bind-attribute-for-a-generic-type.md +++ b/readme/bind-attribute-for-a-generic-type.md @@ -84,8 +84,8 @@ partial class Composition } IDependency transientIDependency1; - Facade localInstance_1182D12742 = _root._singletonFacade43!; - transientIDependency1 = localInstance_1182D12742.GetDependency(); + Facade localInstance_1182D12746 = _root._singletonFacade43!; + transientIDependency1 = localInstance_1182D12746.GetDependency(); return new Service(transientIDependency1); } } diff --git a/readme/bind-attribute-with-lifetime-and-tag.md b/readme/bind-attribute-with-lifetime-and-tag.md index 626ca56d5..72d478a82 100644 --- a/readme/bind-attribute-with-lifetime-and-tag.md +++ b/readme/bind-attribute-with-lifetime-and-tag.md @@ -84,8 +84,8 @@ partial class Composition _root._singletonFacade43 = new Facade(); } - Facade localInstance_1182D12744 = _root._singletonFacade43!; - _root._singletonIDependency0 = localInstance_1182D12744.Dependency; + Facade localInstance_1182D12748 = _root._singletonFacade43!; + _root._singletonIDependency0 = localInstance_1182D12748.Dependency; } } } diff --git a/readme/bind-attribute.md b/readme/bind-attribute.md index d8546cea8..de3640945 100644 --- a/readme/bind-attribute.md +++ b/readme/bind-attribute.md @@ -88,8 +88,8 @@ partial class Composition } IDependency transientIDependency1; - Facade localInstance_1182D12743 = _root._singletonFacade43!; - transientIDependency1 = localInstance_1182D12743.Dependency; + Facade localInstance_1182D12747 = _root._singletonFacade43!; + transientIDependency1 = localInstance_1182D12747.Dependency; return new Service(transientIDependency1); } } diff --git a/readme/build-up-of-an-existing-generic-object.md b/readme/build-up-of-an-existing-generic-object.md index d4e83cf78..716c660f7 100644 --- a/readme/build-up-of-an-existing-generic-object.md +++ b/readme/build-up-of-an-existing-generic-object.md @@ -80,10 +80,10 @@ partial class Composition { Guid transientGuid2 = Guid.NewGuid(); Dependency transientDependency1; - Dependency localDependency48= new Dependency(); - localDependency48.SetId(transientGuid2); - localDependency48.Name = name; - transientDependency1 = localDependency48; + Dependency localDependency52= new Dependency(); + localDependency52.SetId(transientGuid2); + localDependency52.Name = name; + transientDependency1 = localDependency52; return new Service(transientDependency1); } } diff --git a/readme/build-up-of-an-existing-object.md b/readme/build-up-of-an-existing-object.md index 4ecb5c021..4d341319b 100644 --- a/readme/build-up-of-an-existing-object.md +++ b/readme/build-up-of-an-existing-object.md @@ -76,10 +76,10 @@ partial class Composition { Guid transientGuid2 = Guid.NewGuid(); Dependency transientDependency1; - var localDependency45= new Dependency(); - localDependency45.SetId(transientGuid2); - localDependency45.Name = name; - transientDependency1 = localDependency45; + var localDependency49= new Dependency(); + localDependency49.SetId(transientGuid2); + localDependency49.Name = name; + transientDependency1 = localDependency49; return new Service(transientDependency1); } } diff --git a/readme/di-tracing-via-serilog.md b/readme/di-tracing-via-serilog.md index 2ea04741a..f11f5190b 100644 --- a/readme/di-tracing-via-serilog.md +++ b/readme/di-tracing-via-serilog.md @@ -15,7 +15,7 @@ interface IService class Service : IService { - public Service(ILogger log, IDependency dependency) + public Service(Serilog.ILogger log, IDependency dependency) { Dependency = dependency; log.Information("Created"); @@ -24,17 +24,6 @@ class Service : IService public IDependency Dependency { get; } } -interface ILogger: Serilog.ILogger; - -class Logger(Serilog.ILogger logger) : ILogger -{ - private readonly Serilog.ILogger _logger = - logger.ForContext(typeof(T)); - - public void Write(LogEvent logEvent) => - _logger.Write(logEvent); -} - partial class Composition { private void Setup() => @@ -46,12 +35,16 @@ partial class Composition .Hint(Hint.OnNewInstanceImplementationTypeNameRegularExpression, "^((?!Logger).)*$") .Hint(Hint.OnDependencyInjectionContractTypeNameRegularExpression, "^((?!Logger).)*$") - .Arg("logger") - .Bind().As(Lifetime.Singleton).To>() + .Arg("logger", "from arg") + .Bind().To(ctx => + { + ctx.Inject("from arg", out Serilog.ILogger logger); + return logger.ForContext(ctx.OwnerType); + }) .Bind().To() .Bind().To() - .Root>(nameof(Log), kind: RootKinds.Private) + .Root(nameof(Log), kind: RootKinds.Private) .Root(nameof(Root)); [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -77,10 +70,6 @@ The following partial class will be generated: partial class Composition { private readonly Composition _root; - private readonly Lock _lock; - - private Logger? _singletonLogger48; - private Logger? _singletonLogger47; private readonly Serilog.ILogger _argLogger; @@ -89,57 +78,39 @@ partial class Composition { _argLogger = logger ?? throw new ArgumentNullException(nameof(logger)); _root = this; - _lock = new Lock(); } internal Composition(Composition parentScope) { _root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root; _argLogger = _root._argLogger; - _lock = _root._lock; } - public IService Root + private Serilog.ILogger Log { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - Dependency transientDependency1 = new Dependency(); - OnNewInstance(ref transientDependency1, null, Lifetime.Transient); - if (_root._singletonLogger48 is null) - { - using (_lock.EnterScope()) - { - if (_root._singletonLogger48 is null) - { - _root._singletonLogger48 = new Logger(_argLogger); - } - } - } - - Service transientService0 = new Service(_root._singletonLogger48!, OnDependencyInjection(transientDependency1, null, Lifetime.Transient)); - OnNewInstance(ref transientService0, null, Lifetime.Transient); - return OnDependencyInjection(transientService0, null, Lifetime.Transient); + Serilog.ILogger transientILogger0; + Serilog.ILogger localLogger1 = _argLogger; + transientILogger0 = localLogger1.ForContext(typeof(Serilog.ILogger)); + return transientILogger0; } } - private ILogger Log + public IService Root { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (_root._singletonLogger47 is null) - { - using (_lock.EnterScope()) - { - if (_root._singletonLogger47 is null) - { - _root._singletonLogger47 = new Logger(_argLogger); - } - } - } - - return _root._singletonLogger47!; + Dependency transientDependency2 = new Dependency(); + OnNewInstance(ref transientDependency2, null, Lifetime.Transient); + Serilog.ILogger transientILogger1; + Serilog.ILogger localLogger0 = _argLogger; + transientILogger1 = localLogger0.ForContext(typeof(Service)); + Service transientService0 = new Service(transientILogger1, OnDependencyInjection(transientDependency2, null, Lifetime.Transient)); + OnNewInstance(ref transientService0, null, Lifetime.Transient); + return OnDependencyInjection(transientService0, null, Lifetime.Transient); } } @@ -160,19 +131,16 @@ Class diagram: --- classDiagram Service --|> IService - LoggerᐸCompositionᐳ --|> ILoggerᐸCompositionᐳ - LoggerᐸServiceᐳ --|> ILoggerᐸServiceᐳ Dependency --|> IDependency Composition ..> Service : IService Root - Composition ..> LoggerᐸCompositionᐳ : ILoggerᐸCompositionᐳ Log - Service o-- "Singleton" LoggerᐸServiceᐳ : ILoggerᐸServiceᐳ + Composition ..> ILogger : ILogger Log + Service *-- ILogger : ILogger Service *-- Dependency : IDependency - LoggerᐸCompositionᐳ o-- ILogger : Argument "logger" - LoggerᐸServiceᐳ o-- ILogger : Argument "logger" + ILogger o-- ILogger : "from arg" Argument "logger" namespace Pure.DI.UsageTests.Advanced.DITracingViaSerilogScenario { class Composition { <> - -ILoggerᐸCompositionᐳ Log + -ILogger Log +IService Root } class Dependency { @@ -181,28 +149,16 @@ classDiagram class IDependency { <> } - class ILoggerᐸCompositionᐳ { - <> - } - class ILoggerᐸServiceᐳ { - <> - } class IService { <> } - class LoggerᐸCompositionᐳ { - +Logger(ILogger logger) - } - class LoggerᐸServiceᐳ { - +Logger(ILogger logger) - } class Service { - +Service(ILoggerᐸServiceᐳ log, IDependency dependency) + +Service(ILogger log, IDependency dependency) } } namespace Serilog { class ILogger { - <> + <> } } ``` diff --git a/readme/exposed-generic-roots-with-args.md b/readme/exposed-generic-roots-with-args.md index 0ea6566d8..5969357ff 100644 --- a/readme/exposed-generic-roots-with-args.md +++ b/readme/exposed-generic-roots-with-args.md @@ -73,9 +73,9 @@ partial class Composition } Integration.IMyGenericService transientIMyGenericService1; - int localId1 = id; - Integration.CompositionWithGenericRootsAndArgsInOtherProject localInstance_1182D1272 = _root._singletonCompositionWithGenericRootsAndArgsInOtherProject44!; - transientIMyGenericService1 = localInstance_1182D1272.GetMyService(localId1); + int localId3 = id; + Integration.CompositionWithGenericRootsAndArgsInOtherProject localInstance_1182D1274 = _root._singletonCompositionWithGenericRootsAndArgsInOtherProject44!; + transientIMyGenericService1 = localInstance_1182D1274.GetMyService(localId3); return new Program(transientIMyGenericService1); } } diff --git a/readme/exposed-generic-roots.md b/readme/exposed-generic-roots.md index bf39379e7..6ebe88a2b 100644 --- a/readme/exposed-generic-roots.md +++ b/readme/exposed-generic-roots.md @@ -76,8 +76,8 @@ partial class Composition } Integration.IMyGenericService transientIMyGenericService1; - Integration.CompositionWithGenericRootsInOtherProject localInstance_1182D1270 = _root._singletonCompositionWithGenericRootsInOtherProject43!; - transientIMyGenericService1 = localInstance_1182D1270.GetMyService(); + Integration.CompositionWithGenericRootsInOtherProject localInstance_1182D1272 = _root._singletonCompositionWithGenericRootsInOtherProject43!; + transientIMyGenericService1 = localInstance_1182D1272.GetMyService(); return new Program(transientIMyGenericService1); } } diff --git a/readme/exposed-roots-via-arg.md b/readme/exposed-roots-via-arg.md index cf0c80cfe..abfc99c40 100644 --- a/readme/exposed-roots-via-arg.md +++ b/readme/exposed-roots-via-arg.md @@ -60,8 +60,8 @@ partial class Composition get { Integration.IMyService transientIMyService1; - Integration.CompositionInOtherProject localInstance_1182D1274 = _argBaseComposition; - transientIMyService1 = localInstance_1182D1274.MyService; + Integration.CompositionInOtherProject localInstance_1182D1276 = _argBaseComposition; + transientIMyService1 = localInstance_1182D1276.MyService; return new Program(transientIMyService1); } } diff --git a/readme/exposed-roots-via-root-arg.md b/readme/exposed-roots-via-root-arg.md index 21ecc6759..da9e17dee 100644 --- a/readme/exposed-roots-via-root-arg.md +++ b/readme/exposed-roots-via-root-arg.md @@ -55,8 +55,8 @@ partial class Composition public Program GetProgram(Integration.CompositionInOtherProject baseComposition) { Integration.IMyService transientIMyService1; - Integration.CompositionInOtherProject localInstance_1182D1275 = baseComposition; - transientIMyService1 = localInstance_1182D1275.MyService; + Integration.CompositionInOtherProject localInstance_1182D1277 = baseComposition; + transientIMyService1 = localInstance_1182D1277.MyService; return new Program(transientIMyService1); } } diff --git a/readme/exposed-roots-with-tags.md b/readme/exposed-roots-with-tags.md index 06b078eaf..91a941ee5 100644 --- a/readme/exposed-roots-with-tags.md +++ b/readme/exposed-roots-with-tags.md @@ -71,8 +71,8 @@ partial class Composition } Integration.IMyService transientIMyService1; - Integration.CompositionWithTagsInOtherProject localInstance_1182D1276 = _root._singletonCompositionWithTagsInOtherProject43!; - transientIMyService1 = localInstance_1182D1276.MyService; + Integration.CompositionWithTagsInOtherProject localInstance_1182D1278 = _root._singletonCompositionWithTagsInOtherProject43!; + transientIMyService1 = localInstance_1182D1278.MyService; return new Program(transientIMyService1); } } diff --git a/readme/exposed-roots.md b/readme/exposed-roots.md index aaf28d3e5..a08ab849b 100644 --- a/readme/exposed-roots.md +++ b/readme/exposed-roots.md @@ -74,8 +74,8 @@ partial class Composition } Integration.IMyService transientIMyService1; - Integration.CompositionInOtherProject localInstance_1182D1273 = _root._singletonCompositionInOtherProject43!; - transientIMyService1 = localInstance_1182D1273.MyService; + Integration.CompositionInOtherProject localInstance_1182D1275 = _root._singletonCompositionInOtherProject43!; + transientIMyService1 = localInstance_1182D1275.MyService; return new Program(transientIMyService1); } } diff --git a/readme/factory.md b/readme/factory.md index e61b7a566..7eccbaeb4 100644 --- a/readme/factory.md +++ b/readme/factory.md @@ -110,15 +110,15 @@ partial class Composition // Some custom logic for creating an instance. // For example, here's how you can inject and initialize // an instance of a particular type: - bool localIsFake46 = isFake; - if (localIsFake46) + bool localIsFake50 = isFake; + if (localIsFake50) { {transientIDependency1 = new FakeDependency(); goto transientIDependency1Finish; } } - Dependency localDependency47 = new Dependency(transientDateTimeOffset3); - localDependency47.Initialize(); - transientIDependency1 = localDependency47; + Dependency localDependency51 = new Dependency(transientDateTimeOffset3); + localDependency51.Initialize(); + transientIDependency1 = localDependency51; transientIDependency1Finish:; return new Service(transientIDependency1); } diff --git a/readme/func-with-arguments.md b/readme/func-with-arguments.md index 846e92875..1359860b4 100644 --- a/readme/func-with-arguments.md +++ b/readme/func-with-arguments.md @@ -128,8 +128,8 @@ partial class Composition } } - Dependency localDependency52 = new Dependency(_root._singletonClock43!, transientInt323, transientInt324); - return localDependency52; + Dependency localDependency56 = new Dependency(_root._singletonClock43!, transientInt323, transientInt324); + return localDependency56; }; return new Service(transientFunc1); } diff --git a/readme/func-with-tag.md b/readme/func-with-tag.md index 46bf0bb5c..291d269e8 100644 --- a/readme/func-with-tag.md +++ b/readme/func-with-tag.md @@ -60,8 +60,8 @@ partial class Composition { Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue53 = new Dependency(); - return localValue53; + IDependency localValue57 = new Dependency(); + return localValue57; }); return new Service(perBlockFunc1); } diff --git a/readme/func.md b/readme/func.md index 7ddd643d6..4a1ee47f0 100644 --- a/readme/func.md +++ b/readme/func.md @@ -64,8 +64,8 @@ partial class Composition { Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue51 = new Dependency(); - return localValue51; + IDependency localValue55 = new Dependency(); + return localValue55; }); return new Service(perBlockFunc1); } diff --git a/readme/generic-async-composition-roots-with-constraints.md b/readme/generic-async-composition-roots-with-constraints.md index dfc62cba3..edc9978da 100644 --- a/readme/generic-async-composition-roots-with-constraints.md +++ b/readme/generic-async-composition-roots-with-constraints.md @@ -85,29 +85,29 @@ partial class Composition where T2: IDisposable { TaskFactory> perBlockTaskFactory2; - CancellationToken localCancellationToken67 = cancellationToken; + CancellationToken localCancellationToken71 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions68 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions72 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions69 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions73 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler70 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory>(localCancellationToken67, localTaskCreationOptions68, localTaskContinuationOptions69, localTaskScheduler70); + TaskScheduler localTaskScheduler74 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory>(localCancellationToken71, localTaskCreationOptions72, localTaskContinuationOptions73, localTaskScheduler74); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { OtherService transientOtherService6; - IDependency localDependency72 = new Dependency(); - transientOtherService6 = new OtherService(localDependency72); - IService localValue71 = transientOtherService6; - return localValue71; + IDependency localDependency76 = new Dependency(); + transientOtherService6 = new OtherService(localDependency76); + IService localValue75 = transientOtherService6; + return localValue75; }); Task> transientTask0; // Injects an instance factory - Func> localFactory73 = perBlockFunc1; + Func> localFactory77 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory> localTaskFactory74 = perBlockTaskFactory2; + TaskFactory> localTaskFactory78 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory74.StartNew(localFactory73); + transientTask0 = localTaskFactory78.StartNew(localFactory77); return transientTask0; } @@ -117,26 +117,26 @@ partial class Composition where T: struct { TaskFactory> perBlockTaskFactory2; - CancellationToken localCancellationToken75 = cancellationToken; + CancellationToken localCancellationToken79 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions76 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions80 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions77 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions81 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler78 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory>(localCancellationToken75, localTaskCreationOptions76, localTaskContinuationOptions77, localTaskScheduler78); + TaskScheduler localTaskScheduler82 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory>(localCancellationToken79, localTaskCreationOptions80, localTaskContinuationOptions81, localTaskScheduler82); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IService localValue79 = new Service(new Dependency()); - return localValue79; + IService localValue83 = new Service(new Dependency()); + return localValue83; }); Task> transientTask0; // Injects an instance factory - Func> localFactory80 = perBlockFunc1; + Func> localFactory84 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory> localTaskFactory81 = perBlockTaskFactory2; + TaskFactory> localTaskFactory85 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory81.StartNew(localFactory80); + transientTask0 = localTaskFactory85.StartNew(localFactory84); return transientTask0; } } diff --git a/readme/generic-composition-roots-with-constraints.md b/readme/generic-composition-roots-with-constraints.md index 0a0a0a064..25ff096e2 100644 --- a/readme/generic-composition-roots-with-constraints.md +++ b/readme/generic-composition-roots-with-constraints.md @@ -83,8 +83,8 @@ partial class Composition where T2: IDisposable { OtherService transientOtherService0; - IDependency localDependency82 = new Dependency(); - transientOtherService0 = new OtherService(localDependency82); + IDependency localDependency86 = new Dependency(); + transientOtherService0 = new OtherService(localDependency86); return transientOtherService0; } diff --git a/readme/generic-composition-roots.md b/readme/generic-composition-roots.md index 9e6404642..30d38f321 100644 --- a/readme/generic-composition-roots.md +++ b/readme/generic-composition-roots.md @@ -76,8 +76,8 @@ partial class Composition public IService GetOtherService() { OtherService transientOtherService0; - IDependency localDependency83 = new Dependency(); - transientOtherService0 = new OtherService(localDependency83); + IDependency localDependency87 = new Dependency(); + transientOtherService0 = new OtherService(localDependency87); return transientOtherService0; } diff --git a/readme/lazy.md b/readme/lazy.md index f13dba7ed..8096d4a1c 100644 --- a/readme/lazy.md +++ b/readme/lazy.md @@ -55,14 +55,14 @@ partial class Composition { Func perBlockFunc2 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue54 = new Dependency(); - return localValue54; + IDependency localValue58 = new Dependency(); + return localValue58; }); Lazy transientLazy1; // Injects an instance factory - Func localFactory55 = perBlockFunc2; + Func localFactory59 = perBlockFunc2; // Creates an instance that supports lazy initialization - transientLazy1 = new Lazy(localFactory55, true); + transientLazy1 = new Lazy(localFactory59, true); return new Service(transientLazy1); } } diff --git a/readme/manually-started-tasks.md b/readme/manually-started-tasks.md index e0b33e06a..07b86e7da 100644 --- a/readme/manually-started-tasks.md +++ b/readme/manually-started-tasks.md @@ -93,13 +93,13 @@ partial class Composition { Func perBlockFunc2 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue56 = new Dependency(); - return localValue56; + IDependency localValue60 = new Dependency(); + return localValue60; }); Task transientTask1; - Func localFactory57 = perBlockFunc2; - CancellationToken localCancellationToken58 = cancellationToken; - transientTask1 = new Task(localFactory57, localCancellationToken58); + Func localFactory61 = perBlockFunc2; + CancellationToken localCancellationToken62 = cancellationToken; + transientTask1 = new Task(localFactory61, localCancellationToken62); return new Service(transientTask1); } } diff --git a/readme/scope.md b/readme/scope.md index 9d1e7259f..34cdd7499 100644 --- a/readme/scope.md +++ b/readme/scope.md @@ -137,8 +137,8 @@ partial class Composition: IDisposable Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { Composition transientComposition3 = this; - Session localValue89 = new Session(transientComposition3); - return localValue89; + Session localValue93 = new Session(transientComposition3); + return localValue93; }); return new Program(perBlockFunc1); } diff --git a/readme/serilog.md b/readme/serilog.md index 56ea54871..2c3c6e1aa 100644 --- a/readme/serilog.md +++ b/readme/serilog.md @@ -8,7 +8,7 @@ interface IDependency; class Dependency : IDependency { - public Dependency(ILogger log) + public Dependency(Serilog.ILogger log) { log.Information("created"); } @@ -22,7 +22,7 @@ interface IService class Service : IService { public Service( - ILogger log, + Serilog.ILogger log, IDependency dependency) { Dependency = dependency; @@ -32,24 +32,17 @@ class Service : IService public IDependency Dependency { get; } } -interface ILogger: Serilog.ILogger; - -class Logger(Serilog.ILogger logger) : ILogger -{ - private readonly Serilog.ILogger _logger = - logger.ForContext(typeof(T)); - - public void Write(LogEvent logEvent) => - _logger.Write(logEvent); -} - partial class Composition { private void Setup() => DI.Setup(nameof(Composition)) - .Arg("logger") - .Bind().As(Lifetime.Singleton).To>() + .Arg("logger", "from arg") + .Bind().To(ctx => + { + ctx.Inject("from arg", out Serilog.ILogger logger); + return logger.ForContext(ctx.OwnerType); + }) .Bind().To() .Bind().To() @@ -67,10 +60,6 @@ The following partial class will be generated: partial class Composition { private readonly Composition _root; - private readonly Lock _lock; - - private Logger? _singletonLogger47; - private Logger? _singletonLogger48; private readonly Serilog.ILogger _argLogger; @@ -79,14 +68,12 @@ partial class Composition { _argLogger = logger ?? throw new ArgumentNullException(nameof(logger)); _root = this; - _lock = new Lock(); } internal Composition(Composition parentScope) { _root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root; _argLogger = _root._argLogger; - _lock = _root._lock; } public IService Root @@ -94,29 +81,13 @@ partial class Composition [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (_root._singletonLogger48 is null) - { - using (_lock.EnterScope()) - { - if (_root._singletonLogger48 is null) - { - _root._singletonLogger48 = new Logger(_argLogger); - } - } - } - - if (_root._singletonLogger47 is null) - { - using (_lock.EnterScope()) - { - if (_root._singletonLogger47 is null) - { - _root._singletonLogger47 = new Logger(_argLogger); - } - } - } - - return new Service(_root._singletonLogger47!, new Dependency(_root._singletonLogger48!)); + Serilog.ILogger transientILogger3; + Serilog.ILogger localLogger9 = _argLogger; + transientILogger3 = localLogger9.ForContext(typeof(Dependency)); + Serilog.ILogger transientILogger1; + Serilog.ILogger localLogger10 = _argLogger; + transientILogger1 = localLogger10.ForContext(typeof(Service)); + return new Service(transientILogger1, new Dependency(transientILogger3)); } } } @@ -132,43 +103,28 @@ Class diagram: --- classDiagram Service --|> IService - LoggerᐸServiceᐳ --|> ILoggerᐸServiceᐳ Dependency --|> IDependency - LoggerᐸDependencyᐳ --|> ILoggerᐸDependencyᐳ Composition ..> Service : IService Root - Service o-- "Singleton" LoggerᐸServiceᐳ : ILoggerᐸServiceᐳ + Service *-- ILogger : ILogger Service *-- Dependency : IDependency - LoggerᐸServiceᐳ o-- ILogger : Argument "logger" - Dependency o-- "Singleton" LoggerᐸDependencyᐳ : ILoggerᐸDependencyᐳ - LoggerᐸDependencyᐳ o-- ILogger : Argument "logger" + ILogger o-- ILogger : "from arg" Argument "logger" + Dependency *-- ILogger : ILogger namespace Pure.DI.UsageTests.Advanced.SerilogScenario { class Composition { <> +IService Root } class Dependency { - +Dependency(ILoggerᐸDependencyᐳ log) + +Dependency(ILogger log) } class IDependency { <> } - class ILoggerᐸDependencyᐳ { - <> - } - class ILoggerᐸServiceᐳ { - <> - } class IService { <> } - class LoggerᐸDependencyᐳ { - +Logger(ILogger logger) - } - class LoggerᐸServiceᐳ { - +Logger(ILogger logger) - } class Service { - +Service(ILoggerᐸServiceᐳ log, IDependency dependency) + +Service(ILogger log, IDependency dependency) } } namespace Serilog { diff --git a/readme/simplified-factory.md b/readme/simplified-factory.md index ab8274841..1c909e10f 100644 --- a/readme/simplified-factory.md +++ b/readme/simplified-factory.md @@ -82,11 +82,11 @@ partial class Composition get { Dependency transientDependency1; - Dependency localDependency49 = new Dependency(); + Dependency localDependency53 = new Dependency(); DateTimeOffset transientDateTimeOffset3 = DateTimeOffset.Now; - DateTimeOffset localTime50 = transientDateTimeOffset3; - localDependency49.Initialize(localTime50); - transientDependency1 = localDependency49; + DateTimeOffset localTime54 = transientDateTimeOffset3; + localDependency53.Initialize(localTime54); + transientDependency1 = localDependency53; return new Service(transientDependency1); } } diff --git a/readme/task.md b/readme/task.md index 9ffffa8d0..cf44e16c2 100644 --- a/readme/task.md +++ b/readme/task.md @@ -80,26 +80,26 @@ partial class Composition public IService GetRoot(CancellationToken cancellationToken) { TaskFactory perBlockTaskFactory3; - CancellationToken localCancellationToken59 = cancellationToken; + CancellationToken localCancellationToken63 = cancellationToken; TaskCreationOptions transientTaskCreationOptions4 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions60 = transientTaskCreationOptions4; + TaskCreationOptions localTaskCreationOptions64 = transientTaskCreationOptions4; TaskContinuationOptions transientTaskContinuationOptions5 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions61 = transientTaskContinuationOptions5; + TaskContinuationOptions localTaskContinuationOptions65 = transientTaskContinuationOptions5; TaskScheduler transientTaskScheduler6 = TaskScheduler.Current; - TaskScheduler localTaskScheduler62 = transientTaskScheduler6; - perBlockTaskFactory3 = new TaskFactory(localCancellationToken59, localTaskCreationOptions60, localTaskContinuationOptions61, localTaskScheduler62); + TaskScheduler localTaskScheduler66 = transientTaskScheduler6; + perBlockTaskFactory3 = new TaskFactory(localCancellationToken63, localTaskCreationOptions64, localTaskContinuationOptions65, localTaskScheduler66); Func perBlockFunc2 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue63 = new Dependency(); - return localValue63; + IDependency localValue67 = new Dependency(); + return localValue67; }); Task transientTask1; // Injects an instance factory - Func localFactory64 = perBlockFunc2; + Func localFactory68 = perBlockFunc2; // Injects a task factory creating and scheduling task objects - TaskFactory localTaskFactory65 = perBlockTaskFactory3; + TaskFactory localTaskFactory69 = perBlockTaskFactory3; // Creates and starts a task using the instance factory - transientTask1 = localTaskFactory65.StartNew(localFactory64); + transientTask1 = localTaskFactory69.StartNew(localFactory68); return new Service(transientTask1); } } diff --git a/readme/threadsafe-hint.md b/readme/threadsafe-hint.md index 1083f40ed..854c3380e 100644 --- a/readme/threadsafe-hint.md +++ b/readme/threadsafe-hint.md @@ -58,8 +58,8 @@ partial class Composition { Func perBlockFunc0 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue84 = new Dependency(); - return localValue84; + IDependency localValue88 = new Dependency(); + return localValue88; }); _root._singletonService44 = new Service(perBlockFunc0); } diff --git a/readme/tracking-async-disposable-instances-in-delegates.md b/readme/tracking-async-disposable-instances-in-delegates.md index c5461e6bf..d146eba97 100644 --- a/readme/tracking-async-disposable-instances-in-delegates.md +++ b/readme/tracking-async-disposable-instances-in-delegates.md @@ -106,23 +106,23 @@ partial class Composition accumulator47.Add(transientDependency4); } Owned transientOwned3; - Owned localOwned8 = accumulator47; - transientOwned3 = localOwned8; + Owned localOwned12 = accumulator47; + transientOwned3 = localOwned12; using (_lock.EnterScope()) { accumulator47.Add(transientOwned3); } Owned perBlockOwned2; // Creates the owner of an instance - IOwned localOwned9 = transientOwned3; - IDependency localValue10 = transientDependency4; - perBlockOwned2 = new Owned(localValue10, localOwned9); + IOwned localOwned13 = transientOwned3; + IDependency localValue14 = transientDependency4; + perBlockOwned2 = new Owned(localValue14, localOwned13); using (_lock.EnterScope()) { accumulator47.Add(perBlockOwned2); } - Owned localValue7 = perBlockOwned2; - return localValue7; + Owned localValue11 = perBlockOwned2; + return localValue11; }); Service transientService0 = new Service(perBlockFunc1); using (_lock.EnterScope()) diff --git a/readme/tracking-async-disposable-instances-per-a-composition-root.md b/readme/tracking-async-disposable-instances-per-a-composition-root.md index aa2561eec..99b9511db 100644 --- a/readme/tracking-async-disposable-instances-per-a-composition-root.md +++ b/readme/tracking-async-disposable-instances-per-a-composition-root.md @@ -98,15 +98,15 @@ partial class Composition Owned perBlockOwned0; // Creates the owner of an instance Owned transientOwned1; - Owned localOwned13 = accumulator46; - transientOwned1 = localOwned13; + Owned localOwned17 = accumulator46; + transientOwned1 = localOwned17; using (_lock.EnterScope()) { accumulator46.Add(transientOwned1); } - IOwned localOwned11 = transientOwned1; - IService localValue12 = new Service(transientDependency3); - perBlockOwned0 = new Owned(localValue12, localOwned11); + IOwned localOwned15 = transientOwned1; + IService localValue16 = new Service(transientDependency3); + perBlockOwned0 = new Owned(localValue16, localOwned15); using (_lock.EnterScope()) { accumulator46.Add(perBlockOwned0); diff --git a/readme/tracking-disposable-instances-in-delegates.md b/readme/tracking-disposable-instances-in-delegates.md index 889016524..20df019b8 100644 --- a/readme/tracking-disposable-instances-in-delegates.md +++ b/readme/tracking-disposable-instances-in-delegates.md @@ -99,23 +99,23 @@ partial class Composition accumulator47.Add(transientDependency4); } Owned transientOwned3; - Owned localOwned15 = accumulator47; - transientOwned3 = localOwned15; + Owned localOwned19 = accumulator47; + transientOwned3 = localOwned19; using (_lock.EnterScope()) { accumulator47.Add(transientOwned3); } Owned perBlockOwned2; // Creates the owner of an instance - IOwned localOwned16 = transientOwned3; - IDependency localValue17 = transientDependency4; - perBlockOwned2 = new Owned(localValue17, localOwned16); + IOwned localOwned20 = transientOwned3; + IDependency localValue21 = transientDependency4; + perBlockOwned2 = new Owned(localValue21, localOwned20); using (_lock.EnterScope()) { accumulator47.Add(perBlockOwned2); } - Owned localValue14 = perBlockOwned2; - return localValue14; + Owned localValue18 = perBlockOwned2; + return localValue18; }); Service transientService0 = new Service(perBlockFunc1); using (_lock.EnterScope()) diff --git a/readme/tracking-disposable-instances-per-a-composition-root.md b/readme/tracking-disposable-instances-per-a-composition-root.md index dda3ded73..34f36c6bf 100644 --- a/readme/tracking-disposable-instances-per-a-composition-root.md +++ b/readme/tracking-disposable-instances-per-a-composition-root.md @@ -94,15 +94,15 @@ partial class Composition Owned perBlockOwned0; // Creates the owner of an instance Owned transientOwned1; - Owned localOwned20 = accumulator46; - transientOwned1 = localOwned20; + Owned localOwned24 = accumulator46; + transientOwned1 = localOwned24; using (_lock.EnterScope()) { accumulator46.Add(transientOwned1); } - IOwned localOwned18 = transientOwned1; - IService localValue19 = new Service(transientDependency3); - perBlockOwned0 = new Owned(localValue19, localOwned18); + IOwned localOwned22 = transientOwned1; + IService localValue23 = new Service(transientDependency3); + perBlockOwned0 = new Owned(localValue23, localOwned22); using (_lock.EnterScope()) { accumulator46.Add(perBlockOwned0); diff --git a/readme/tracking-disposable-instances-using-pre-built-classes.md b/readme/tracking-disposable-instances-using-pre-built-classes.md index aafbb4221..795e4246d 100644 --- a/readme/tracking-disposable-instances-using-pre-built-classes.md +++ b/readme/tracking-disposable-instances-using-pre-built-classes.md @@ -147,15 +147,15 @@ partial class Composition: IDisposable Abstractions.Own perBlockOwn3; // Creates the owner of an instance - Abstractions.Own localOwn22 = accumulator50; - IDependency localValue23 = _root._singletonDependency44!; - perBlockOwn3 = new Abstractions.Own(localValue23, localOwn22); + Abstractions.Own localOwn26 = accumulator50; + IDependency localValue27 = _root._singletonDependency44!; + perBlockOwn3 = new Abstractions.Own(localValue27, localOwn26); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwn3); } - Abstractions.Own localValue21 = perBlockOwn3; - return localValue21; + Abstractions.Own localValue25 = perBlockOwn3; + return localValue25; }); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { @@ -167,15 +167,15 @@ partial class Composition: IDisposable } Abstractions.Own perBlockOwn5; // Creates the owner of an instance - Abstractions.Own localOwn25 = accumulator50; - IDependency localValue26 = transientDependency7; - perBlockOwn5 = new Abstractions.Own(localValue26, localOwn25); + Abstractions.Own localOwn29 = accumulator50; + IDependency localValue30 = transientDependency7; + perBlockOwn5 = new Abstractions.Own(localValue30, localOwn29); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwn5); } - Abstractions.Own localValue24 = perBlockOwn5; - return localValue24; + Abstractions.Own localValue28 = perBlockOwn5; + return localValue28; }); Service transientService0 = new Service(perBlockFunc1, perBlockFunc2); using (_lock.EnterScope()) diff --git a/readme/tracking-disposable-instances-with-different-lifetimes.md b/readme/tracking-disposable-instances-with-different-lifetimes.md index 3707173df..056db1ccf 100644 --- a/readme/tracking-disposable-instances-with-different-lifetimes.md +++ b/readme/tracking-disposable-instances-with-different-lifetimes.md @@ -136,23 +136,23 @@ partial class Composition: IDisposable } Owned transientOwned4; - Owned localOwned28 = accumulator50; - transientOwned4 = localOwned28; + Owned localOwned32 = accumulator50; + transientOwned4 = localOwned32; using (_lock.EnterScope()) { accumulator50.Add(transientOwned4); } Owned perBlockOwned3; // Creates the owner of an instance - IOwned localOwned29 = transientOwned4; - IDependency localValue30 = _root._singletonDependency44!; - perBlockOwned3 = new Owned(localValue30, localOwned29); + IOwned localOwned33 = transientOwned4; + IDependency localValue34 = _root._singletonDependency44!; + perBlockOwned3 = new Owned(localValue34, localOwned33); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwned3); } - Owned localValue27 = perBlockOwned3; - return localValue27; + Owned localValue31 = perBlockOwned3; + return localValue31; }); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { @@ -163,23 +163,23 @@ partial class Composition: IDisposable accumulator50.Add(transientDependency8); } Owned transientOwned7; - Owned localOwned32 = accumulator50; - transientOwned7 = localOwned32; + Owned localOwned36 = accumulator50; + transientOwned7 = localOwned36; using (_lock.EnterScope()) { accumulator50.Add(transientOwned7); } Owned perBlockOwned6; // Creates the owner of an instance - IOwned localOwned33 = transientOwned7; - IDependency localValue34 = transientDependency8; - perBlockOwned6 = new Owned(localValue34, localOwned33); + IOwned localOwned37 = transientOwned7; + IDependency localValue38 = transientDependency8; + perBlockOwned6 = new Owned(localValue38, localOwned37); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwned6); } - Owned localValue31 = perBlockOwned6; - return localValue31; + Owned localValue35 = perBlockOwned6; + return localValue35; }); Service transientService0 = new Service(perBlockFunc1, perBlockFunc2); using (_lock.EnterScope()) diff --git a/readme/valuetask.md b/readme/valuetask.md index 0620d5b40..8ce54a96f 100644 --- a/readme/valuetask.md +++ b/readme/valuetask.md @@ -64,9 +64,9 @@ partial class Composition get { ValueTask transientValueTask1; - IDependency localValue66 = new Dependency(); + IDependency localValue70 = new Dependency(); // Initializes a new instance of the ValueTask class using the supplied instance - transientValueTask1 = new ValueTask(localValue66); + transientValueTask1 = new ValueTask(localValue70); return new Service(transientValueTask1); } } diff --git a/src/Pure.DI.Core/Components/Api.g.cs b/src/Pure.DI.Core/Components/Api.g.cs index f9f31b947..7bf699107 100644 --- a/src/Pure.DI.Core/Components/Api.g.cs +++ b/src/Pure.DI.Core/Components/Api.g.cs @@ -2431,7 +2431,17 @@ internal interface IContext /// /// object Tag { get; } - + + /// + /// The owner type of the instance being created. Cannot be used outside of the binding setup. See also + ///
For the instance, this is the owner type. + ///
For instances of and , this is the composition type. + ///
For the instance, this is the type that generated the block. + ///
For a instance, it is the composition root type. + ///
+ /// + Type OwnerType { get; } + /// /// Injects an instance of type T. Cannot be used outside of the binding setup. /// diff --git a/src/Pure.DI.Core/Core/Code/BuildContext.cs b/src/Pure.DI.Core/Core/Code/BuildContext.cs index d8f0fb915..29bfa34f9 100644 --- a/src/Pure.DI.Core/Core/Code/BuildContext.cs +++ b/src/Pure.DI.Core/Core/Code/BuildContext.cs @@ -9,6 +9,7 @@ internal record BuildContext( LinesBuilder Code, LinesBuilder LocalFunctionsCode, object? ContextTag, + string OwnerTypeName, bool? LockIsRequired, ImmutableArray Accumulators, bool IsFactory = false); \ No newline at end of file diff --git a/src/Pure.DI.Core/Core/Code/CompositionBuilder.cs b/src/Pure.DI.Core/Core/Code/CompositionBuilder.cs index b450825f2..f4eecf0d0 100644 --- a/src/Pure.DI.Core/Core/Code/CompositionBuilder.cs +++ b/src/Pure.DI.Core/Core/Code/CompositionBuilder.cs @@ -34,6 +34,7 @@ public CompositionCode Build(DependencyGraph graph) new LinesBuilder(), new LinesBuilder(), root.Injection.Tag != MdTag.ContextTag ? root.Injection.Tag : null, + graph.Source.Name.FullName, null, root.Node.Accumulators.ToImmutableArray()); diff --git a/src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs b/src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs index 0ffa00d3c..1d5309fe8 100644 --- a/src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs +++ b/src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs @@ -156,7 +156,7 @@ public void Build(BuildContext ctx, in DpFactory factory) var injections = new List(); var inits = new List(); var factoryRewriter = new FactoryRewriter(arguments, compilations, factory, variable, finishLabel, injections, inits, triviaTools); - var lambda = factoryRewriter.Rewrite(factoryExpression); + var lambda = factoryRewriter.Rewrite(ctx, factoryExpression); new FactoryValidator(factory).Validate(lambda); SyntaxNode syntaxNode = lambda.Block is not null ? lambda.Block : SyntaxFactory.ExpressionStatement((ExpressionSyntax)lambda.Body); var lines = new List(); diff --git a/src/Pure.DI.Core/Core/Code/FactoryRewriter.cs b/src/Pure.DI.Core/Core/Code/FactoryRewriter.cs index aefe3023e..c7310d548 100644 --- a/src/Pure.DI.Core/Core/Code/FactoryRewriter.cs +++ b/src/Pure.DI.Core/Core/Code/FactoryRewriter.cs @@ -26,11 +26,15 @@ internal sealed class FactoryRewriter( private static readonly IdentifierNameSyntax InitializationMarkerExpression = SyntaxFactory.IdentifierName(Names.InitializationMarker); private int _nestedLambdaCounter; private int _nestedBlockCounter; + private BuildContext? _ctx; public bool IsFinishMarkRequired { get; private set; } - public LambdaExpressionSyntax Rewrite(LambdaExpressionSyntax lambda) => - (LambdaExpressionSyntax)Visit(lambda); + public LambdaExpressionSyntax Rewrite(BuildContext ctx, LambdaExpressionSyntax lambda) + { + _ctx = ctx; + return (LambdaExpressionSyntax)Visit(lambda); + } public override SyntaxNode? VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node) { @@ -241,10 +245,17 @@ private bool TryInitialize( public override SyntaxNode? VisitMemberAccessExpression(MemberAccessExpressionSyntax node) { if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression) - && node is { Expression: IdentifierNameSyntax identifierName, Name.Identifier.Text: nameof(IContext.Tag) } + && node is { Expression: IdentifierNameSyntax identifierName } && identifierName.Identifier.Text == factory.Source.Context.Identifier.Text) { - return SyntaxFactory.ParseExpression(variable.Injection.Tag.ValueToString()); + switch (node.Name.Identifier.Text) + { + case nameof(IContext.Tag): + return SyntaxFactory.ParseExpression(variable.Injection.Tag.ValueToString()); + + case nameof(IContext.OwnerType) when _ctx is {} ctx: + return SyntaxFactory.ParseExpression($"typeof({ctx.OwnerTypeName})"); + } } return base.VisitMemberAccessExpression(node); diff --git a/src/Pure.DI.Core/Core/Code/StatementCodeBuilder.cs b/src/Pure.DI.Core/Core/Code/StatementCodeBuilder.cs index 22564181e..dd306bf32 100644 --- a/src/Pure.DI.Core/Core/Code/StatementCodeBuilder.cs +++ b/src/Pure.DI.Core/Core/Code/StatementCodeBuilder.cs @@ -11,11 +11,22 @@ internal class StatementCodeBuilder( { public void Build(BuildContext ctx, in IStatement statement) { - if (statement.Current.Injection.Tag != MdTag.ContextTag) + var curVariable = statement.Current; + if (curVariable.Injection.Tag != MdTag.ContextTag) { - ctx = ctx with { ContextTag = statement.Current.Injection.Tag }; + ctx = ctx with { ContextTag = curVariable.Injection.Tag }; } + var ownerTypeName = curVariable.Node.Lifetime switch + { + Lifetime.Transient => curVariable.TargetNode.Type.ToDisplayString(), + Lifetime.PerResolve => statement.GetPath().Last().Current.Node.Type.ToDisplayString(), + Lifetime.PerBlock => statement.Current.ParentBlock.Current.Node.Type.ToDisplayString(), + _ => ctx.DependencyGraph.Source.Name.FullName + }; + + ctx = ctx with { OwnerTypeName = ownerTypeName }; + switch (statement) { case Variable variable: diff --git a/src/Pure.DI.Core/Core/Code/Variable.cs b/src/Pure.DI.Core/Core/Code/Variable.cs index e56b980ed..c734f58af 100644 --- a/src/Pure.DI.Core/Core/Code/Variable.cs +++ b/src/Pure.DI.Core/Core/Code/Variable.cs @@ -5,6 +5,7 @@ internal record Variable( IStatement? Parent, int PerLifetimeId, in DependencyNode Node, + in DependencyNode TargetNode, in Injection Injection, ICollection Args, VariableInfo Info, diff --git a/src/Pure.DI.Core/Core/Code/VariablesBuilder.cs b/src/Pure.DI.Core/Core/Code/VariablesBuilder.cs index 0391e4d02..597764751 100644 --- a/src/Pure.DI.Core/Core/Code/VariablesBuilder.cs +++ b/src/Pure.DI.Core/Core/Code/VariablesBuilder.cs @@ -25,6 +25,7 @@ public Block Build( map, blockMap, rootNode, + rootNode, rootInjection, ref transientId)); @@ -124,6 +125,7 @@ public Block Build( map, blockMap, depNode with { Accumulators = accumulators }, + variable.Node, depInjection, ref transientId, cycleVariable); @@ -195,6 +197,7 @@ private Variable GetVariable( IDictionary map, IDictionary<(MdBinding, object?, int), Variable> blockMap, DependencyNode node, + DependencyNode targetNode, in Injection injection, ref int transientId, Variable? cycleVariable = null) @@ -217,7 +220,7 @@ private Variable GetVariable( { case Lifetime.Transient: { - var transientVariable = new Variable(setup, parentBlock, transientId++, node, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); + var transientVariable = new Variable(setup, parentBlock, transientId++, node, targetNode, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); if (node.Construct?.Source.Kind == MdConstructKind.Accumulator) { transientVariable.VariableCode = GetAccumulatorName(transientVariable); @@ -239,7 +242,7 @@ private Variable GetVariable( }; } - blockVariable = new Variable(setup, parentBlock, transientId++, node, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); + blockVariable = new Variable(setup, parentBlock, transientId++, node, targetNode, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); blockMap.Add(perBlockKey, blockVariable); return blockVariable; } @@ -258,7 +261,7 @@ private Variable GetVariable( }; } - variable = new Variable(setup, parentBlock, node.Binding.Id, node, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); + variable = new Variable(setup, parentBlock, node.Binding.Id, node, targetNode, injection, new List(), new VariableInfo(), nodeInfo.IsLazy(node), false); map.Add(key, variable); return variable; } diff --git a/tests/Pure.DI.IntegrationTests/FactoryTests.cs b/tests/Pure.DI.IntegrationTests/FactoryTests.cs index 61212e831..41286e279 100644 --- a/tests/Pure.DI.IntegrationTests/FactoryTests.cs +++ b/tests/Pure.DI.IntegrationTests/FactoryTests.cs @@ -753,6 +753,89 @@ public static void Main() result.Success.ShouldBeTrue(result); result.StdOut.ShouldBe([output, "Created"], result); } + + [Theory] + /*[InlineData(nameof(Lifetime.Transient), "Service")] + [InlineData(nameof(Lifetime.Singleton), "Composition")] + [InlineData(nameof(Lifetime.Scoped), "Composition")] + [InlineData(nameof(Lifetime.PerBlock), "Service")]*/ + [InlineData(nameof(Lifetime.PerResolve), "Service")] + public async Task ShouldSupportFactoryWhenUsingOwnerType(string lifetime, string owner) + { + // Given + + // When + var result = await """ + using System; + using Pure.DI; + + namespace Sample + { + interface IDependency + { + } + + class Dependency: IDependency + { + public Dependency(string owner) + { + Console.WriteLine(owner); + } + } + + interface IService + { + IDependency Dep { get; } + } + + class Service: IService + { + public Service(IDependency dep) + { + Dep = dep; + Console.WriteLine("Created"); + } + + public IDependency Dep { get; } + } + + internal partial class Composition + { + private partial T OnDependencyInjection(in T value, object? tag, Lifetime lifetime) + { + return value; + } + } + + static class Setup + { + private static void SetupComposition() + { + // OnDependencyInjection = On + DI.Setup("Composition") + .Bind().As(Lifetime.#lifetime#).To(ctx => new Dependency(ctx.OwnerType.Name)) + .Bind().To() + .Root("Service"); + } + } + + public class Program + { + public static void Main() + { + var composition = new Composition(); + var service = composition.Service; + } + } + } + """ + .Replace("#lifetime#", lifetime) + .RunAsync(new Options(LanguageVersion.CSharp9)); + + // Then + result.Success.ShouldBeTrue(result); + result.StdOut.ShouldBe([owner, "Created"], result); + } [Fact] public async Task ShouldSupportFactoryWithInjectInFunc() diff --git a/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs b/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs index 292ec1666..904225725 100644 --- a/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs +++ b/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs @@ -37,7 +37,7 @@ interface IService class Service : IService { - public Service(ILogger log, IDependency dependency) + public Service(Serilog.ILogger log, IDependency dependency) { Dependency = dependency; log.Information("Created"); @@ -46,17 +46,6 @@ public Service(ILogger log, IDependency dependency) public IDependency Dependency { get; } } -interface ILogger: Serilog.ILogger; - -class Logger(Serilog.ILogger logger) : ILogger -{ - private readonly Serilog.ILogger _logger = - logger.ForContext(typeof(T)); - - public void Write(LogEvent logEvent) => - _logger.Write(logEvent); -} - partial class Composition { private void Setup() => @@ -70,12 +59,16 @@ private void Setup() => .Hint(Hint.OnNewInstanceImplementationTypeNameRegularExpression, "^((?!Logger).)*$") .Hint(Hint.OnDependencyInjectionContractTypeNameRegularExpression, "^((?!Logger).)*$") - .Arg("logger") - .Bind().As(Lifetime.Singleton).To>() + .Arg("logger", "from arg") + .Bind().To(ctx => + { + ctx.Inject("from arg", out Serilog.ILogger logger); + return logger.ForContext(ctx.OwnerType); + }) .Bind().To() .Bind().To() - .Root>(nameof(Log), kind: RootKinds.Private) + .Root(nameof(Log), kind: RootKinds.Private) .Root(nameof(Root)); [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/tests/Pure.DI.UsageTests/Advanced/SerilogScenario.cs b/tests/Pure.DI.UsageTests/Advanced/SerilogScenario.cs index 9bd629d2a..7e0d719b0 100644 --- a/tests/Pure.DI.UsageTests/Advanced/SerilogScenario.cs +++ b/tests/Pure.DI.UsageTests/Advanced/SerilogScenario.cs @@ -27,7 +27,7 @@ interface IDependency; class Dependency : IDependency { - public Dependency(ILogger log) + public Dependency(Serilog.ILogger log) { log.Information("created"); } @@ -41,7 +41,7 @@ interface IService class Service : IService { public Service( - ILogger log, + Serilog.ILogger log, IDependency dependency) { Dependency = dependency; @@ -51,17 +51,6 @@ public Service( public IDependency Dependency { get; } } -interface ILogger: Serilog.ILogger; - -class Logger(Serilog.ILogger logger) : ILogger -{ - private readonly Serilog.ILogger _logger = - logger.ForContext(typeof(T)); - - public void Write(LogEvent logEvent) => - _logger.Write(logEvent); -} - partial class Composition { private void Setup() => @@ -69,8 +58,12 @@ private void Setup() => // } .Hint(Hint.Resolve, "Off") // { - .Arg("logger") - .Bind().As(Lifetime.Singleton).To>() + .Arg("logger", "from arg") + .Bind().To(ctx => + { + ctx.Inject("from arg", out Serilog.ILogger logger); + return logger.ForContext(ctx.OwnerType); + }) .Bind().To() .Bind().To()