-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
18eccab
commit a662eac
Showing
3 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#### 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(IDependency dependency) : IService | ||
{ | ||
public IDependency Dependency { get; } = dependency; | ||
} | ||
|
||
interface ILogger<T>: Serilog.ILogger; | ||
|
||
class Logger<T>(Serilog.ILogger logger) : ILogger<T> | ||
{ | ||
private readonly Serilog.ILogger _logger = | ||
logger.ForContext(typeof(T)); | ||
|
||
public void Write(LogEvent logEvent) => | ||
_logger.Write(logEvent); | ||
} | ||
|
||
partial class Composition: ILogEventSink | ||
{ | ||
private readonly Action<LogEvent>? _eventsHandler; | ||
private readonly ILogger<Composition>? _logger; | ||
|
||
public Composition(Action<LogEvent> eventsHandler) | ||
: this() | ||
{ | ||
_eventsHandler = eventsHandler; | ||
_logger = new Logger<Composition>( | ||
new Serilog.LoggerConfiguration() | ||
.WriteTo.Sink(this) | ||
.CreateLogger().ForContext<Composition>()); | ||
} | ||
|
||
private void Setup() => | ||
DI.Setup(nameof(Composition)) | ||
|
||
.Hint(Hint.OnNewInstance, "On") | ||
.Hint(Hint.OnDependencyInjection, "On") | ||
.Bind().To(_ => _logger!) | ||
.Bind().As(Lifetime.Singleton).To<Logger<TT>>() | ||
|
||
.Bind().To<Dependency>() | ||
.Bind().To<Service>() | ||
.Root<IService>(nameof(Root)); | ||
|
||
public void Emit(LogEvent logEvent) => | ||
_eventsHandler?.Invoke(logEvent); | ||
|
||
partial void OnNewInstance<T>(ref T value, object? tag, Lifetime lifetime) => | ||
_logger?.Information("Created [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); | ||
|
||
private partial T OnDependencyInjection<T>(in T value, object? tag, Lifetime lifetime) | ||
{ | ||
_logger?.Information("Injected [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); | ||
return value; | ||
} | ||
} | ||
|
||
var events = new List<LogEvent>(); | ||
var composition = new Composition(logEvent => events.Add(logEvent)); | ||
var service = composition.Root; | ||
``` | ||
|
||
The following partial class will be generated: | ||
|
||
```c# | ||
partial class Composition | ||
{ | ||
private readonly Composition _root; | ||
|
||
[OrdinalAttribute(256)] | ||
public Composition() | ||
{ | ||
_root = this; | ||
} | ||
|
||
internal Composition(Composition parentScope) | ||
{ | ||
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root; | ||
} | ||
|
||
public IService Root | ||
{ | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
get | ||
{ | ||
Dependency transientDependency1 = new Dependency(); | ||
OnNewInstance<Dependency>(ref transientDependency1, null, Lifetime.Transient); | ||
Service transientService0 = new Service(OnDependencyInjection<IDependency>(transientDependency1, null, Lifetime.Transient)); | ||
OnNewInstance<Service>(ref transientService0, null, Lifetime.Transient); | ||
return OnDependencyInjection<IService>(transientService0, null, Lifetime.Transient); | ||
} | ||
} | ||
|
||
|
||
partial void OnNewInstance<T>(ref T value, object? tag, Lifetime lifetime); | ||
|
||
private partial T OnDependencyInjection<T>(in T value, object? tag, Lifetime lifetime); | ||
} | ||
``` | ||
|
||
Class diagram: | ||
|
||
```mermaid | ||
--- | ||
config: | ||
class: | ||
hideEmptyMembersBox: true | ||
--- | ||
classDiagram | ||
Service --|> IService | ||
Dependency --|> IDependency | ||
Composition ..> Service : IService Root | ||
Service *-- Dependency : IDependency | ||
namespace Pure.DI.UsageTests.Advanced.DITracingViaSerilogScenario { | ||
class Composition { | ||
<<partial>> | ||
+IService Root | ||
} | ||
class Dependency { | ||
+Dependency() | ||
} | ||
class IDependency { | ||
<<interface>> | ||
} | ||
class IService { | ||
<<interface>> | ||
} | ||
class Service { | ||
+Service(IDependency dependency) | ||
} | ||
} | ||
``` | ||
|
116 changes: 116 additions & 0 deletions
116
tests/Pure.DI.UsageTests/Advanced/DITracingViaSerilogScenario.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
$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 Serilog.Core; | ||
using Serilog.Events; | ||
using Xunit; | ||
|
||
// { | ||
interface IDependency; | ||
|
||
class Dependency : IDependency; | ||
|
||
interface IService | ||
{ | ||
IDependency Dependency { get; } | ||
} | ||
|
||
class Service(IDependency dependency) : IService | ||
{ | ||
public IDependency Dependency { get; } = dependency; | ||
} | ||
|
||
interface ILogger<T>: Serilog.ILogger; | ||
|
||
class Logger<T>(Serilog.ILogger logger) : ILogger<T> | ||
{ | ||
private readonly Serilog.ILogger _logger = | ||
logger.ForContext(typeof(T)); | ||
|
||
public void Write(LogEvent logEvent) => | ||
_logger.Write(logEvent); | ||
} | ||
|
||
partial class Composition: ILogEventSink | ||
{ | ||
private readonly Action<LogEvent>? _eventsHandler; | ||
private readonly ILogger<Composition>? _logger; | ||
|
||
public Composition(Action<LogEvent> eventsHandler) | ||
: this() | ||
{ | ||
_eventsHandler = eventsHandler; | ||
_logger = new Logger<Composition>( | ||
new Serilog.LoggerConfiguration() | ||
.WriteTo.Sink(this) | ||
.CreateLogger().ForContext<Composition>()); | ||
} | ||
|
||
private void Setup() => | ||
DI.Setup(nameof(Composition)) | ||
// } | ||
.Hint(Hint.Resolve, "Off") | ||
// { | ||
.Hint(Hint.OnNewInstance, "On") | ||
.Hint(Hint.OnDependencyInjection, "On") | ||
.Bind().To(_ => _logger!) | ||
.Bind().As(Lifetime.Singleton).To<Logger<TT>>() | ||
|
||
.Bind().To<Dependency>() | ||
.Bind().To<Service>() | ||
.Root<IService>(nameof(Root)); | ||
|
||
public void Emit(LogEvent logEvent) => | ||
_eventsHandler?.Invoke(logEvent); | ||
|
||
partial void OnNewInstance<T>(ref T value, object? tag, Lifetime lifetime) => | ||
_logger?.Information("Created [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); | ||
|
||
private partial T OnDependencyInjection<T>(in T value, object? tag, Lifetime lifetime) | ||
{ | ||
_logger?.Information("Injected [{Value}], tag [{Tag}] as {Lifetime}", value, tag, lifetime); | ||
return value; | ||
} | ||
} | ||
// } | ||
|
||
class EventSink(ICollection<LogEvent> events) | ||
: ILogEventSink | ||
{ | ||
public void Emit(LogEvent logEvent) => | ||
events.Add(logEvent); | ||
} | ||
|
||
public class Scenario | ||
{ | ||
[Fact] | ||
public void Run() | ||
{ | ||
// { | ||
var events = new List<LogEvent>(); | ||
var composition = new Composition(logEvent => events.Add(logEvent)); | ||
var service = composition.Root; | ||
// } | ||
events.Count.ShouldBe(4); | ||
composition.SaveClassDiagram(); | ||
} | ||
} |