From 6e652c59214e5bad1c4742c405992ca8cf6fdd70 Mon Sep 17 00:00:00 2001 From: Nikolay Pianikov Date: Mon, 16 Dec 2024 11:43:19 +0300 Subject: [PATCH] Add example --- README.md | 1 + readme/advanced-interception.md | 1 + 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 | 193 ++++++++++++++++++ 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/interception.md | 1 + readme/lazy.md | 8 +- readme/manually-started-tasks.md | 10 +- readme/scope.md | 4 +- readme/simplified-factory.md | 8 +- readme/task.md | 20 +- readme/threadsafe-hint.md | 4 +- ...async-disposable-instances-in-delegates.md | 19 +- ...osable-instances-per-a-composition-root.md | 19 +- ...cking-disposable-instances-in-delegates.md | 23 ++- ...osable-instances-per-a-composition-root.md | 19 +- ...sable-instances-using-pre-built-classes.md | 20 +- ...able-instances-with-different-lifetimes.md | 50 +++-- readme/valuetask.md | 4 +- src/Pure.DI.Core/Features/Default.g.cs | 2 +- .../Advanced/DITracingViaSerilogScenario.cs | 118 +++++++++++ .../AdvancedInterceptionScenario.cs | 2 + .../Interception/InterceptionScenario.cs | 2 + 36 files changed, 522 insertions(+), 142 deletions(-) create mode 100644 readme/di-tracing-via-serilog.md create mode 100644 tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs diff --git a/README.md b/README.md index 922211b0d..829005625 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ dotnet run - [Exposed generic roots](readme/exposed-generic-roots.md) - [Exposed generic roots with args](readme/exposed-generic-roots-with-args.md) - [Serilog](readme/serilog.md) +- [DI tracing via serilog](readme/di-tracing-via-serilog.md) ### Applications - Console - [Schrödinger's cat](readme/Console.md) diff --git a/readme/advanced-interception.md b/readme/advanced-interception.md index c53300238..37bac4afd 100644 --- a/readme/advanced-interception.md +++ b/readme/advanced-interception.md @@ -43,6 +43,7 @@ internal partial class Composition : IInterceptor _interceptors = [this]; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private partial T OnDependencyInjection( in T value, object? tag, diff --git a/readme/async-disposable-scope.md b/readme/async-disposable-scope.md index c18b20c2e..964d0fc1b 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 localValue79 = new Session(transientComposition3); - return localValue79; + Session localValue85 = new Session(transientComposition3); + return localValue85; }); return new Program(perBlockFunc1); } diff --git a/readme/async-root.md b/readme/async-root.md index df30854a6..e57e170a5 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 localCancellationToken29 = cancellationToken; + CancellationToken localCancellationToken35 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions30 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions36 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions31 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions37 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler32 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory(localCancellationToken29, localTaskCreationOptions30, localTaskContinuationOptions31, localTaskScheduler32); + TaskScheduler localTaskScheduler38 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory(localCancellationToken35, localTaskCreationOptions36, localTaskContinuationOptions37, localTaskScheduler38); Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IService localValue33 = new Service(new Dependency()); - return localValue33; + IService localValue39 = new Service(new Dependency()); + return localValue39; }); Task transientTask0; // Injects an instance factory - Func localFactory34 = perBlockFunc1; + Func localFactory40 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory localTaskFactory35 = perBlockTaskFactory2; + TaskFactory localTaskFactory41 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory35.StartNew(localFactory34); + transientTask0 = localTaskFactory41.StartNew(localFactory40); return transientTask0; } } diff --git a/readme/auto-scoped.md b/readme/auto-scoped.md index a24c9f07b..052b2eb9f 100644 --- a/readme/auto-scoped.md +++ b/readme/auto-scoped.md @@ -96,13 +96,13 @@ partial class Composition { Composition transientComposition3 = this; IService transientIService2; - Composition localBaseComposition81 = transientComposition3; + Composition localBaseComposition87 = transientComposition3; // Creates a session - var localSession82= new Composition(localBaseComposition81); + var localSession88= new Composition(localBaseComposition87); // Provides a root - transientIService2 = localSession82.SessionRoot; - IService localValue80 = transientIService2; - return localValue80; + transientIService2 = localSession88.SessionRoot; + IService localValue86 = transientIService2; + return localValue86; }); 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 fc8b78b41..69ef03fb6 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_1182D12736 = _root._singletonFacade43!; - transientIDependency1 = localInstance_1182D12736.GetDependency(); + Facade localInstance_1182D12742 = _root._singletonFacade43!; + transientIDependency1 = localInstance_1182D12742.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 101fb13ab..626ca56d5 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_1182D12738 = _root._singletonFacade43!; - _root._singletonIDependency0 = localInstance_1182D12738.Dependency; + Facade localInstance_1182D12744 = _root._singletonFacade43!; + _root._singletonIDependency0 = localInstance_1182D12744.Dependency; } } } diff --git a/readme/bind-attribute.md b/readme/bind-attribute.md index b9c7cb113..d8546cea8 100644 --- a/readme/bind-attribute.md +++ b/readme/bind-attribute.md @@ -88,8 +88,8 @@ partial class Composition } IDependency transientIDependency1; - Facade localInstance_1182D12737 = _root._singletonFacade43!; - transientIDependency1 = localInstance_1182D12737.Dependency; + Facade localInstance_1182D12743 = _root._singletonFacade43!; + transientIDependency1 = localInstance_1182D12743.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 893add094..d4e83cf78 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 localDependency42= new Dependency(); - localDependency42.SetId(transientGuid2); - localDependency42.Name = name; - transientDependency1 = localDependency42; + Dependency localDependency48= new Dependency(); + localDependency48.SetId(transientGuid2); + localDependency48.Name = name; + transientDependency1 = localDependency48; 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 9a2832016..4ecb5c021 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 localDependency39= new Dependency(); - localDependency39.SetId(transientGuid2); - localDependency39.Name = name; - transientDependency1 = localDependency39; + var localDependency45= new Dependency(); + localDependency45.SetId(transientGuid2); + localDependency45.Name = name; + transientDependency1 = localDependency45; return new Service(transientDependency1); } } diff --git a/readme/di-tracing-via-serilog.md b/readme/di-tracing-via-serilog.md new file mode 100644 index 000000000..7b7ed69a0 --- /dev/null +++ b/readme/di-tracing-via-serilog.md @@ -0,0 +1,193 @@ +#### DI tracing via serilog + +[![CSharp](https://img.shields.io/badge/C%23-code-blue.svg)](../tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs) + + +```c# +interface IDependency; + +class Dependency : IDependency; + +interface IService +{ + IDependency Dependency { get; } +} + +class Service : IService +{ + public Service(ILogger log, IDependency dependency) + { + Dependency = dependency; + log.Information("Created"); + } + + 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)) + + .Hint(Hint.OnNewInstance, "On") + .Hint(Hint.OnDependencyInjection, "On") + .Arg("logger") + .Bind().As(Lifetime.Singleton).To>() + + .Bind().To() + .Bind().To() + .Root(nameof(Log), kind: RootKinds.Private) + .Root(nameof(Root)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + partial void OnNewInstance(ref T value, object? tag, Lifetime lifetime) => + Log.Information("Created [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private partial T OnDependencyInjection(in T value, object? tag, Lifetime lifetime) + { + if (typeof(T) != typeof(Serilog.ILogger)) + { + Log.Information("Injected [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); + } + + return value; + } +} + +Serilog.ILogger serilogLogger = CreateLogger(); +var composition = new Composition(logger: serilogLogger); +var service = composition.Root; +``` + +The following partial class will be generated: + +```c# +partial class Composition +{ + private readonly Composition _root; + private readonly Lock _lock; + + private Logger? _singletonLogger47; + + private readonly Serilog.ILogger _argLogger; + + [OrdinalAttribute(128)] + public Composition(Serilog.ILogger logger) + { + _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; + } + + private Serilog.ILogger Log + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return OnDependencyInjection(_argLogger, null, Lifetime.Transient); + } + } + + public IService Root + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + Dependency transientDependency1 = new Dependency(); + OnNewInstance(ref transientDependency1, null, Lifetime.Transient); + if (_root._singletonLogger47 is null) + { + using (_lock.EnterScope()) + { + if (_root._singletonLogger47 is null) + { + Logger _singletonLogger47Temp; + _singletonLogger47Temp = new Logger(OnDependencyInjection(_argLogger, null, Lifetime.Transient)); + OnNewInstance>(ref _singletonLogger47Temp, null, Lifetime.Singleton); + Thread.MemoryBarrier(); + _root._singletonLogger47 = _singletonLogger47Temp; + } + } + } + + Service transientService0 = new Service(OnDependencyInjection>(_root._singletonLogger47!, null, Lifetime.Singleton), OnDependencyInjection(transientDependency1, null, Lifetime.Transient)); + OnNewInstance(ref transientService0, null, Lifetime.Transient); + return OnDependencyInjection(transientService0, null, Lifetime.Transient); + } + } + + + partial void OnNewInstance(ref T value, object? tag, Lifetime lifetime); + + private partial T OnDependencyInjection(in T value, object? tag, Lifetime lifetime); +} +``` + +Class diagram: + +```mermaid +--- + config: + class: + hideEmptyMembersBox: true +--- +classDiagram + Service --|> IService + LoggerᐸServiceᐳ --|> ILoggerᐸServiceᐳ + Dependency --|> IDependency + Composition ..> Service : IService Root + Composition ..> ILogger : ILogger Log + Service o-- "Singleton" LoggerᐸServiceᐳ : ILoggerᐸServiceᐳ + Service *-- Dependency : IDependency + LoggerᐸServiceᐳ o-- ILogger : Argument "logger" + namespace Pure.DI.UsageTests.Advanced.DITracingViaSerilogScenario { + class Composition { + <> + -ILogger Log + +IService Root + } + class Dependency { + +Dependency() + } + class IDependency { + <> + } + class ILoggerᐸServiceᐳ { + <> + } + class IService { + <> + } + class LoggerᐸServiceᐳ { + +Logger(ILogger logger) + } + class Service { + +Service(ILoggerᐸServiceᐳ log, IDependency dependency) + } + } + namespace Serilog { + class ILogger { + <> + } + } +``` + diff --git a/readme/factory.md b/readme/factory.md index cbfd3a4c6..e61b7a566 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 localIsFake40 = isFake; - if (localIsFake40) + bool localIsFake46 = isFake; + if (localIsFake46) { {transientIDependency1 = new FakeDependency(); goto transientIDependency1Finish; } } - Dependency localDependency41 = new Dependency(transientDateTimeOffset3); - localDependency41.Initialize(); - transientIDependency1 = localDependency41; + Dependency localDependency47 = new Dependency(transientDateTimeOffset3); + localDependency47.Initialize(); + transientIDependency1 = localDependency47; transientIDependency1Finish:; return new Service(transientIDependency1); } diff --git a/readme/func-with-arguments.md b/readme/func-with-arguments.md index 4fa7d203b..846e92875 100644 --- a/readme/func-with-arguments.md +++ b/readme/func-with-arguments.md @@ -128,8 +128,8 @@ partial class Composition } } - Dependency localDependency46 = new Dependency(_root._singletonClock43!, transientInt323, transientInt324); - return localDependency46; + Dependency localDependency52 = new Dependency(_root._singletonClock43!, transientInt323, transientInt324); + return localDependency52; }; return new Service(transientFunc1); } diff --git a/readme/func-with-tag.md b/readme/func-with-tag.md index c66a6eb31..46bf0bb5c 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 localValue47 = new Dependency(); - return localValue47; + IDependency localValue53 = new Dependency(); + return localValue53; }); return new Service(perBlockFunc1); } diff --git a/readme/func.md b/readme/func.md index 3d586760f..7ddd643d6 100644 --- a/readme/func.md +++ b/readme/func.md @@ -64,8 +64,8 @@ partial class Composition { Func perBlockFunc1 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue45 = new Dependency(); - return localValue45; + IDependency localValue51 = new Dependency(); + return localValue51; }); 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 4dc4ab445..dfc62cba3 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 localCancellationToken61 = cancellationToken; + CancellationToken localCancellationToken67 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions62 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions68 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions63 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions69 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler64 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory>(localCancellationToken61, localTaskCreationOptions62, localTaskContinuationOptions63, localTaskScheduler64); + TaskScheduler localTaskScheduler70 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory>(localCancellationToken67, localTaskCreationOptions68, localTaskContinuationOptions69, localTaskScheduler70); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { OtherService transientOtherService6; - IDependency localDependency66 = new Dependency(); - transientOtherService6 = new OtherService(localDependency66); - IService localValue65 = transientOtherService6; - return localValue65; + IDependency localDependency72 = new Dependency(); + transientOtherService6 = new OtherService(localDependency72); + IService localValue71 = transientOtherService6; + return localValue71; }); Task> transientTask0; // Injects an instance factory - Func> localFactory67 = perBlockFunc1; + Func> localFactory73 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory> localTaskFactory68 = perBlockTaskFactory2; + TaskFactory> localTaskFactory74 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory68.StartNew(localFactory67); + transientTask0 = localTaskFactory74.StartNew(localFactory73); return transientTask0; } @@ -117,26 +117,26 @@ partial class Composition where T: struct { TaskFactory> perBlockTaskFactory2; - CancellationToken localCancellationToken69 = cancellationToken; + CancellationToken localCancellationToken75 = cancellationToken; TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions70 = transientTaskCreationOptions3; + TaskCreationOptions localTaskCreationOptions76 = transientTaskCreationOptions3; TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions71 = transientTaskContinuationOptions4; + TaskContinuationOptions localTaskContinuationOptions77 = transientTaskContinuationOptions4; TaskScheduler transientTaskScheduler5 = TaskScheduler.Default; - TaskScheduler localTaskScheduler72 = transientTaskScheduler5; - perBlockTaskFactory2 = new TaskFactory>(localCancellationToken69, localTaskCreationOptions70, localTaskContinuationOptions71, localTaskScheduler72); + TaskScheduler localTaskScheduler78 = transientTaskScheduler5; + perBlockTaskFactory2 = new TaskFactory>(localCancellationToken75, localTaskCreationOptions76, localTaskContinuationOptions77, localTaskScheduler78); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IService localValue73 = new Service(new Dependency()); - return localValue73; + IService localValue79 = new Service(new Dependency()); + return localValue79; }); Task> transientTask0; // Injects an instance factory - Func> localFactory74 = perBlockFunc1; + Func> localFactory80 = perBlockFunc1; // Injects a task factory creating and scheduling task objects - TaskFactory> localTaskFactory75 = perBlockTaskFactory2; + TaskFactory> localTaskFactory81 = perBlockTaskFactory2; // Creates and starts a task using the instance factory - transientTask0 = localTaskFactory75.StartNew(localFactory74); + transientTask0 = localTaskFactory81.StartNew(localFactory80); return transientTask0; } } diff --git a/readme/generic-composition-roots-with-constraints.md b/readme/generic-composition-roots-with-constraints.md index 4a3328950..0a0a0a064 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 localDependency76 = new Dependency(); - transientOtherService0 = new OtherService(localDependency76); + IDependency localDependency82 = new Dependency(); + transientOtherService0 = new OtherService(localDependency82); return transientOtherService0; } diff --git a/readme/generic-composition-roots.md b/readme/generic-composition-roots.md index 5b2b0fe35..9e6404642 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 localDependency77 = new Dependency(); - transientOtherService0 = new OtherService(localDependency77); + IDependency localDependency83 = new Dependency(); + transientOtherService0 = new OtherService(localDependency83); return transientOtherService0; } diff --git a/readme/interception.md b/readme/interception.md index c60931145..b5644ea9e 100644 --- a/readme/interception.md +++ b/readme/interception.md @@ -20,6 +20,7 @@ partial class Composition : IInterceptor { private static readonly ProxyGenerator ProxyGenerator = new(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] private partial T OnDependencyInjection( in T value, object? tag, diff --git a/readme/lazy.md b/readme/lazy.md index 9b40121c9..f13dba7ed 100644 --- a/readme/lazy.md +++ b/readme/lazy.md @@ -55,14 +55,14 @@ partial class Composition { Func perBlockFunc2 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue48 = new Dependency(); - return localValue48; + IDependency localValue54 = new Dependency(); + return localValue54; }); Lazy transientLazy1; // Injects an instance factory - Func localFactory49 = perBlockFunc2; + Func localFactory55 = perBlockFunc2; // Creates an instance that supports lazy initialization - transientLazy1 = new Lazy(localFactory49, true); + transientLazy1 = new Lazy(localFactory55, true); return new Service(transientLazy1); } } diff --git a/readme/manually-started-tasks.md b/readme/manually-started-tasks.md index 95c106cc7..e0b33e06a 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 localValue50 = new Dependency(); - return localValue50; + IDependency localValue56 = new Dependency(); + return localValue56; }); Task transientTask1; - Func localFactory51 = perBlockFunc2; - CancellationToken localCancellationToken52 = cancellationToken; - transientTask1 = new Task(localFactory51, localCancellationToken52); + Func localFactory57 = perBlockFunc2; + CancellationToken localCancellationToken58 = cancellationToken; + transientTask1 = new Task(localFactory57, localCancellationToken58); return new Service(transientTask1); } } diff --git a/readme/scope.md b/readme/scope.md index 5c23055b7..9d1e7259f 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 localValue83 = new Session(transientComposition3); - return localValue83; + Session localValue89 = new Session(transientComposition3); + return localValue89; }); return new Program(perBlockFunc1); } diff --git a/readme/simplified-factory.md b/readme/simplified-factory.md index 3663595f2..ab8274841 100644 --- a/readme/simplified-factory.md +++ b/readme/simplified-factory.md @@ -82,11 +82,11 @@ partial class Composition get { Dependency transientDependency1; - Dependency localDependency43 = new Dependency(); + Dependency localDependency49 = new Dependency(); DateTimeOffset transientDateTimeOffset3 = DateTimeOffset.Now; - DateTimeOffset localTime44 = transientDateTimeOffset3; - localDependency43.Initialize(localTime44); - transientDependency1 = localDependency43; + DateTimeOffset localTime50 = transientDateTimeOffset3; + localDependency49.Initialize(localTime50); + transientDependency1 = localDependency49; return new Service(transientDependency1); } } diff --git a/readme/task.md b/readme/task.md index 9ffd38923..9ffffa8d0 100644 --- a/readme/task.md +++ b/readme/task.md @@ -80,26 +80,26 @@ partial class Composition public IService GetRoot(CancellationToken cancellationToken) { TaskFactory perBlockTaskFactory3; - CancellationToken localCancellationToken53 = cancellationToken; + CancellationToken localCancellationToken59 = cancellationToken; TaskCreationOptions transientTaskCreationOptions4 = TaskCreationOptions.None; - TaskCreationOptions localTaskCreationOptions54 = transientTaskCreationOptions4; + TaskCreationOptions localTaskCreationOptions60 = transientTaskCreationOptions4; TaskContinuationOptions transientTaskContinuationOptions5 = TaskContinuationOptions.None; - TaskContinuationOptions localTaskContinuationOptions55 = transientTaskContinuationOptions5; + TaskContinuationOptions localTaskContinuationOptions61 = transientTaskContinuationOptions5; TaskScheduler transientTaskScheduler6 = TaskScheduler.Current; - TaskScheduler localTaskScheduler56 = transientTaskScheduler6; - perBlockTaskFactory3 = new TaskFactory(localCancellationToken53, localTaskCreationOptions54, localTaskContinuationOptions55, localTaskScheduler56); + TaskScheduler localTaskScheduler62 = transientTaskScheduler6; + perBlockTaskFactory3 = new TaskFactory(localCancellationToken59, localTaskCreationOptions60, localTaskContinuationOptions61, localTaskScheduler62); Func perBlockFunc2 = new Func([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { - IDependency localValue57 = new Dependency(); - return localValue57; + IDependency localValue63 = new Dependency(); + return localValue63; }); Task transientTask1; // Injects an instance factory - Func localFactory58 = perBlockFunc2; + Func localFactory64 = perBlockFunc2; // Injects a task factory creating and scheduling task objects - TaskFactory localTaskFactory59 = perBlockTaskFactory3; + TaskFactory localTaskFactory65 = perBlockTaskFactory3; // Creates and starts a task using the instance factory - transientTask1 = localTaskFactory59.StartNew(localFactory58); + transientTask1 = localTaskFactory65.StartNew(localFactory64); return new Service(transientTask1); } } diff --git a/readme/threadsafe-hint.md b/readme/threadsafe-hint.md index 323b02774..1083f40ed 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 localValue78 = new Dependency(); - return localValue78; + IDependency localValue84 = new Dependency(); + return localValue84; }); _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 b4eba345c..c5461e6bf 100644 --- a/readme/tracking-async-disposable-instances-in-delegates.md +++ b/readme/tracking-async-disposable-instances-in-delegates.md @@ -105,11 +105,18 @@ partial class Composition { accumulator47.Add(transientDependency4); } + Owned transientOwned3; + Owned localOwned8 = accumulator47; + transientOwned3 = localOwned8; + using (_lock.EnterScope()) + { + accumulator47.Add(transientOwned3); + } Owned perBlockOwned2; // Creates the owner of an instance - Owned localOwned8 = accumulator47; - IDependency localValue9 = transientDependency4; - perBlockOwned2 = new Owned(localValue9, localOwned8); + IOwned localOwned9 = transientOwned3; + IDependency localValue10 = transientDependency4; + perBlockOwned2 = new Owned(localValue10, localOwned9); using (_lock.EnterScope()) { accumulator47.Add(perBlockOwned2); @@ -251,13 +258,17 @@ Class diagram: hideEmptyMembersBox: true --- classDiagram + Owned --|> IOwned Dependency --|> IDependency Composition ..> Service : Service Root Service o-- "PerBlock" FuncᐸOwnedᐸIDependencyᐳᐳ : FuncᐸOwnedᐸIDependencyᐳᐳ FuncᐸOwnedᐸIDependencyᐳᐳ o-- "PerBlock" OwnedᐸIDependencyᐳ : OwnedᐸIDependencyᐳ - OwnedᐸIDependencyᐳ *-- Owned : Owned + OwnedᐸIDependencyᐳ *-- Owned : IOwned OwnedᐸIDependencyᐳ *-- Dependency : IDependency namespace Pure.DI { + class IOwned { + <> + } class Owned { } class OwnedᐸIDependencyᐳ { 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 f62aa0882..aa2561eec 100644 --- a/readme/tracking-async-disposable-instances-per-a-composition-root.md +++ b/readme/tracking-async-disposable-instances-per-a-composition-root.md @@ -97,9 +97,16 @@ partial class Composition } Owned perBlockOwned0; // Creates the owner of an instance - Owned localOwned10 = accumulator46; - IService localValue11 = new Service(transientDependency3); - perBlockOwned0 = new Owned(localValue11, localOwned10); + Owned transientOwned1; + Owned localOwned13 = accumulator46; + transientOwned1 = localOwned13; + using (_lock.EnterScope()) + { + accumulator46.Add(transientOwned1); + } + IOwned localOwned11 = transientOwned1; + IService localValue12 = new Service(transientDependency3); + perBlockOwned0 = new Owned(localValue12, localOwned11); using (_lock.EnterScope()) { accumulator46.Add(perBlockOwned0); @@ -161,14 +168,18 @@ Class diagram: hideEmptyMembersBox: true --- classDiagram + Owned --|> IOwned Service --|> IService Dependency --|> IDependency Dependency --|> IAsyncDisposable Composition ..> OwnedᐸIServiceᐳ : OwnedᐸIServiceᐳ Root - OwnedᐸIServiceᐳ *-- Owned : Owned + OwnedᐸIServiceᐳ *-- Owned : IOwned OwnedᐸIServiceᐳ *-- Service : IService Service *-- Dependency : IDependency namespace Pure.DI { + class IOwned { + <> + } class Owned { } class OwnedᐸIServiceᐳ { diff --git a/readme/tracking-disposable-instances-in-delegates.md b/readme/tracking-disposable-instances-in-delegates.md index 1b01b4a36..889016524 100644 --- a/readme/tracking-disposable-instances-in-delegates.md +++ b/readme/tracking-disposable-instances-in-delegates.md @@ -98,17 +98,24 @@ partial class Composition { accumulator47.Add(transientDependency4); } + Owned transientOwned3; + Owned localOwned15 = accumulator47; + transientOwned3 = localOwned15; + using (_lock.EnterScope()) + { + accumulator47.Add(transientOwned3); + } Owned perBlockOwned2; // Creates the owner of an instance - Owned localOwned13 = accumulator47; - IDependency localValue14 = transientDependency4; - perBlockOwned2 = new Owned(localValue14, localOwned13); + IOwned localOwned16 = transientOwned3; + IDependency localValue17 = transientDependency4; + perBlockOwned2 = new Owned(localValue17, localOwned16); using (_lock.EnterScope()) { accumulator47.Add(perBlockOwned2); } - Owned localValue12 = perBlockOwned2; - return localValue12; + Owned localValue14 = perBlockOwned2; + return localValue14; }); Service transientService0 = new Service(perBlockFunc1); using (_lock.EnterScope()) @@ -244,13 +251,17 @@ Class diagram: hideEmptyMembersBox: true --- classDiagram + Owned --|> IOwned Dependency --|> IDependency Composition ..> Service : Service Root Service o-- "PerBlock" FuncᐸOwnedᐸIDependencyᐳᐳ : FuncᐸOwnedᐸIDependencyᐳᐳ FuncᐸOwnedᐸIDependencyᐳᐳ o-- "PerBlock" OwnedᐸIDependencyᐳ : OwnedᐸIDependencyᐳ - OwnedᐸIDependencyᐳ *-- Owned : Owned + OwnedᐸIDependencyᐳ *-- Owned : IOwned OwnedᐸIDependencyᐳ *-- Dependency : IDependency namespace Pure.DI { + class IOwned { + <> + } class Owned { } class OwnedᐸIDependencyᐳ { diff --git a/readme/tracking-disposable-instances-per-a-composition-root.md b/readme/tracking-disposable-instances-per-a-composition-root.md index 08a385256..dda3ded73 100644 --- a/readme/tracking-disposable-instances-per-a-composition-root.md +++ b/readme/tracking-disposable-instances-per-a-composition-root.md @@ -93,9 +93,16 @@ partial class Composition } Owned perBlockOwned0; // Creates the owner of an instance - Owned localOwned15 = accumulator46; - IService localValue16 = new Service(transientDependency3); - perBlockOwned0 = new Owned(localValue16, localOwned15); + Owned transientOwned1; + Owned localOwned20 = accumulator46; + transientOwned1 = localOwned20; + using (_lock.EnterScope()) + { + accumulator46.Add(transientOwned1); + } + IOwned localOwned18 = transientOwned1; + IService localValue19 = new Service(transientDependency3); + perBlockOwned0 = new Owned(localValue19, localOwned18); using (_lock.EnterScope()) { accumulator46.Add(perBlockOwned0); @@ -157,13 +164,17 @@ Class diagram: hideEmptyMembersBox: true --- classDiagram + Owned --|> IOwned Service --|> IService Dependency --|> IDependency Composition ..> OwnedᐸIServiceᐳ : OwnedᐸIServiceᐳ Root - OwnedᐸIServiceᐳ *-- Owned : Owned + OwnedᐸIServiceᐳ *-- Owned : IOwned OwnedᐸIServiceᐳ *-- Service : IService Service *-- Dependency : IDependency namespace Pure.DI { + class IOwned { + <> + } class Owned { } class OwnedᐸIServiceᐳ { diff --git a/readme/tracking-disposable-instances-using-pre-built-classes.md b/readme/tracking-disposable-instances-using-pre-built-classes.md index e9a27b77b..aafbb4221 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 localOwn18 = accumulator50; - IDependency localValue19 = _root._singletonDependency44!; - perBlockOwn3 = new Abstractions.Own(localValue19, localOwn18); + Abstractions.Own localOwn22 = accumulator50; + IDependency localValue23 = _root._singletonDependency44!; + perBlockOwn3 = new Abstractions.Own(localValue23, localOwn22); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwn3); } - Abstractions.Own localValue17 = perBlockOwn3; - return localValue17; + Abstractions.Own localValue21 = perBlockOwn3; + return localValue21; }); 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 localOwn21 = accumulator50; - IDependency localValue22 = transientDependency7; - perBlockOwn5 = new Abstractions.Own(localValue22, localOwn21); + Abstractions.Own localOwn25 = accumulator50; + IDependency localValue26 = transientDependency7; + perBlockOwn5 = new Abstractions.Own(localValue26, localOwn25); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwn5); } - Abstractions.Own localValue20 = perBlockOwn5; - return localValue20; + Abstractions.Own localValue24 = perBlockOwn5; + return localValue24; }); 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 cd0b7dea2..3707173df 100644 --- a/readme/tracking-disposable-instances-with-different-lifetimes.md +++ b/readme/tracking-disposable-instances-with-different-lifetimes.md @@ -135,37 +135,51 @@ partial class Composition: IDisposable } } + Owned transientOwned4; + Owned localOwned28 = accumulator50; + transientOwned4 = localOwned28; + using (_lock.EnterScope()) + { + accumulator50.Add(transientOwned4); + } Owned perBlockOwned3; // Creates the owner of an instance - Owned localOwned24 = accumulator50; - IDependency localValue25 = _root._singletonDependency44!; - perBlockOwned3 = new Owned(localValue25, localOwned24); + IOwned localOwned29 = transientOwned4; + IDependency localValue30 = _root._singletonDependency44!; + perBlockOwned3 = new Owned(localValue30, localOwned29); using (_lock.EnterScope()) { accumulator50.Add(perBlockOwned3); } - Owned localValue23 = perBlockOwned3; - return localValue23; + Owned localValue27 = perBlockOwned3; + return localValue27; }); Func> perBlockFunc1 = new Func>([MethodImpl(MethodImplOptions.AggressiveInlining)] () => { var accumulator50 = new Owned(); - Dependency transientDependency7 = new Dependency(); + Dependency transientDependency8 = new Dependency(); + using (_lock.EnterScope()) + { + accumulator50.Add(transientDependency8); + } + Owned transientOwned7; + Owned localOwned32 = accumulator50; + transientOwned7 = localOwned32; using (_lock.EnterScope()) { - accumulator50.Add(transientDependency7); + accumulator50.Add(transientOwned7); } - Owned perBlockOwned5; + Owned perBlockOwned6; // Creates the owner of an instance - Owned localOwned27 = accumulator50; - IDependency localValue28 = transientDependency7; - perBlockOwned5 = new Owned(localValue28, localOwned27); + IOwned localOwned33 = transientOwned7; + IDependency localValue34 = transientDependency8; + perBlockOwned6 = new Owned(localValue34, localOwned33); using (_lock.EnterScope()) { - accumulator50.Add(perBlockOwned5); + accumulator50.Add(perBlockOwned6); } - Owned localValue26 = perBlockOwned5; - return localValue26; + Owned localValue31 = perBlockOwned6; + return localValue31; }); Service transientService0 = new Service(perBlockFunc1, perBlockFunc2); using (_lock.EnterScope()) @@ -335,17 +349,21 @@ Class diagram: --- classDiagram Composition --|> IDisposable + Owned --|> IOwned Dependency --|> IDependency Composition ..> Service : Service Root Service o-- "PerBlock" FuncᐸOwnedᐸIDependencyᐳᐳ : FuncᐸOwnedᐸIDependencyᐳᐳ Service o-- "PerBlock" FuncᐸOwnedᐸIDependencyᐳᐳ : "single" FuncᐸOwnedᐸIDependencyᐳᐳ FuncᐸOwnedᐸIDependencyᐳᐳ o-- "PerBlock" OwnedᐸIDependencyᐳ : OwnedᐸIDependencyᐳ FuncᐸOwnedᐸIDependencyᐳᐳ o-- "PerBlock" OwnedᐸIDependencyᐳ : "single" OwnedᐸIDependencyᐳ - OwnedᐸIDependencyᐳ *-- Owned : Owned + OwnedᐸIDependencyᐳ *-- Owned : IOwned OwnedᐸIDependencyᐳ *-- Dependency : IDependency - OwnedᐸIDependencyᐳ *-- Owned : Owned + OwnedᐸIDependencyᐳ *-- Owned : IOwned OwnedᐸIDependencyᐳ o-- "Singleton" Dependency : "single" IDependency namespace Pure.DI { + class IOwned { + <> + } class Owned { } class OwnedᐸIDependencyᐳ { diff --git a/readme/valuetask.md b/readme/valuetask.md index a1435c947..0620d5b40 100644 --- a/readme/valuetask.md +++ b/readme/valuetask.md @@ -64,9 +64,9 @@ partial class Composition get { ValueTask transientValueTask1; - IDependency localValue60 = new Dependency(); + IDependency localValue66 = new Dependency(); // Initializes a new instance of the ValueTask class using the supplied instance - transientValueTask1 = new ValueTask(localValue60); + transientValueTask1 = new ValueTask(localValue66); return new Service(transientValueTask1); } } diff --git a/src/Pure.DI.Core/Features/Default.g.cs b/src/Pure.DI.Core/Features/Default.g.cs index 3c9977e8e..4034b827f 100644 --- a/src/Pure.DI.Core/Features/Default.g.cs +++ b/src/Pure.DI.Core/Features/Default.g.cs @@ -29,7 +29,7 @@ private static void Setup() .As(Lifetime.PerBlock) .To(ctx => { // Creates the owner of an instance - ctx.Inject(out var owned); + ctx.Inject(out var owned); ctx.Inject(ctx.Tag, out var value); return new Owned(value, owned); }) diff --git a/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs b/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs new file mode 100644 index 000000000..502106125 --- /dev/null +++ b/tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs @@ -0,0 +1,118 @@ +/* +$v=true +$p=302 +$d=DI tracing via serilog +*/ + +// ReSharper disable ClassNeverInstantiated.Local +// ReSharper disable CheckNamespace +// ReSharper disable UnusedType.Global +// ReSharper disable ArrangeTypeModifiers +// ReSharper disable ClassNeverInstantiated.Global +// ReSharper disable UnusedVariable + +// ReSharper disable UnusedTypeParameter +// ReSharper disable UnusedMember.Local +// ReSharper disable UnusedMemberInSuper.Global +// ReSharper disable UnusedMember.Global +#pragma warning disable CS9113 // Parameter is unread. +#pragma warning disable CA1859 +namespace Pure.DI.UsageTests.Advanced.DITracingViaSerilogScenario; + +#pragma warning disable CA2263 +using System.Runtime.CompilerServices; +using Serilog.Core; +using Serilog.Events; +using Xunit; + +// { +interface IDependency; + +class Dependency : IDependency; + +interface IService +{ + IDependency Dependency { get; } +} + +class Service : IService +{ + public Service(ILogger log, IDependency dependency) + { + Dependency = dependency; + log.Information("Created"); + } + + 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)) +// } + .Hint(Hint.Resolve, "Off") +// { + .Hint(Hint.OnNewInstance, "On") + .Hint(Hint.OnDependencyInjection, "On") + .Arg("logger") + .Bind().As(Lifetime.Singleton).To>() + + .Bind().To() + .Bind().To() + .Root(nameof(Log), kind: RootKinds.Private) + .Root(nameof(Root)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + partial void OnNewInstance(ref T value, object? tag, Lifetime lifetime) => + Log.Information("Created [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private partial T OnDependencyInjection(in T value, object? tag, Lifetime lifetime) + { + if (typeof(T) != typeof(Serilog.ILogger)) + { + Log.Information("Injected [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); + } + + return value; + } +} +// } + +class EventSink(ICollection events) + : ILogEventSink +{ + public void Emit(LogEvent logEvent) => + events.Add(logEvent); +} + +public class Scenario +{ + [Fact] + public void Run() + { + var events = new List(); + var serilogLogger = new Serilog.LoggerConfiguration() + .WriteTo.Sink(new EventSink(events)) + .CreateLogger(); +// { + //# Serilog.ILogger serilogLogger = CreateLogger(); + var composition = new Composition(logger: serilogLogger); + var service = composition.Root; +// } + events.Count.ShouldBe(7); + composition.SaveClassDiagram(); + } +} \ No newline at end of file diff --git a/tests/Pure.DI.UsageTests/Interception/AdvancedInterceptionScenario.cs b/tests/Pure.DI.UsageTests/Interception/AdvancedInterceptionScenario.cs index 725e88a98..d900617b0 100644 --- a/tests/Pure.DI.UsageTests/Interception/AdvancedInterceptionScenario.cs +++ b/tests/Pure.DI.UsageTests/Interception/AdvancedInterceptionScenario.cs @@ -16,6 +16,7 @@ namespace Pure.DI.UsageTests.Interception.AdvancedInterceptionScenario; using System.Collections.Immutable; using System.Linq.Expressions; +using System.Runtime.CompilerServices; using Castle.DynamicProxy; using Shouldly; using Xunit; @@ -58,6 +59,7 @@ public Composition(List log) _interceptors = [this]; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private partial T OnDependencyInjection( in T value, object? tag, diff --git a/tests/Pure.DI.UsageTests/Interception/InterceptionScenario.cs b/tests/Pure.DI.UsageTests/Interception/InterceptionScenario.cs index 26eae3cac..c2ca04d20 100644 --- a/tests/Pure.DI.UsageTests/Interception/InterceptionScenario.cs +++ b/tests/Pure.DI.UsageTests/Interception/InterceptionScenario.cs @@ -28,6 +28,7 @@ namespace Pure.DI.UsageTests.Interception.InterceptionScenario; +using System.Runtime.CompilerServices; using Castle.DynamicProxy; using Shouldly; using Xunit; @@ -47,6 +48,7 @@ partial class Composition : IInterceptor { private static readonly ProxyGenerator ProxyGenerator = new(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] private partial T OnDependencyInjection( in T value, object? tag,