Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed May 9, 2024
1 parent 1cb87d4 commit 10b0ead
Show file tree
Hide file tree
Showing 111 changed files with 713 additions and 1,942 deletions.
68 changes: 29 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

![](readme/di.gif)

## Usage requirements

Supports .NET starting with .NET Framework 2.0 released 2005-10-27 and all newer versions.

- Installed [.NET SDK 6.0.4](https://dotnet.microsoft.com/download/dotnet/6.0) or later
- Using [C# 8](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80) or later

## Key features

Pure.DI is not a framework or library, but a source code generator for creating object graphs. To make them accurate, the developer uses a set of intuitive hints from the Pure.DI API. During the compilation phase, Pure.DI determines the optimal graph structure, checks its correctness, and generates partial class code to create object graphs in the Pure DI paradigm using only basic language constructs. The resulting generated code is robust, works everywhere, throws no exceptions, does not depend on .NET library calls or .NET reflections, is efficient in terms of performance and memory consumption, and is subject to all optimizations. This code can be easily integrated into an application because it does not use unnecessary delegates, additional calls to any methods, type conversions, boxing/unboxing, etc.
Expand Down Expand Up @@ -52,30 +59,22 @@ interface ICat
State State { get; }
}

enum State
{
Alive,
Dead
}
enum State { Alive, Dead }
```

### Here's our implementation

```c#
class CardboardBox<T>(T content) : IBox<T>
{
public T Content { get; } = content;

public override string ToString() => $"[{Content}]";
public T Content { get; } = content;
}

class ShroedingersCat(Lazy<State> superposition) : ICat
{
// The decoherence of the superposition
// at the time of observation via an irreversible process
public State State => superposition.Value;

public override string ToString() => $"{State} cat";
public State State => superposition.Value;
}

```
Expand All @@ -94,14 +93,14 @@ Let's bind the abstractions to their implementations and set up the creation of
DI.Setup(nameof(Composition))
// Models a random subatomic event that may or may not occur
.Bind().As(Singleton).To<Random>()
// Represents a quantum superposition of 2 states: Alive or Dead
// Quantum superposition of two states: Alive or Dead
.Bind().To(ctx =>
{
ctx.Inject<Random>(out var random);
return (State)random.Next(2);
})
.Bind().To<ShroedingersCat>()
// Represents a cardboard box with any contents
// Cardboard box with any contents
.Bind().To<CardboardBox<TT>>()
// Composition Root
.Root<Program>("Root");
Expand All @@ -113,27 +112,27 @@ The above code specifies the generation of a partial class named *__Composition_
partial class Composition
{
private object _lock = new object();
private Random _random;
private Random? _random;

public Program Root
{
get
{
Func<State> stateFunc = new Func<State>(() =>
{
if (_random == null)
{
lock (_lock)
var stateFunc = new Func<State>(() =>
{
if (_random == null)
{
_random = new Random();
lock (_lock)
{
if (_random == null)
{
_random = new Random();
}
}
}
}
}

return (State)_random.Next(2);
});

return (State)_random.Next(2);
});

return new Program(
new CardboardBox<ICat>(
Expand Down Expand Up @@ -197,25 +196,18 @@ dotnet run
- [Auto-bindings](readme/auto-bindings.md)
- [Injections of abstractions](readme/injections-of-abstractions.md)
- [Composition roots](readme/composition-roots.md)
- [Composition roots simplified](readme/composition-roots-simplified.md)
- [Resolve methods](readme/resolve-methods.md)
- [Simplified binding](readme/simplified-binding.md)
- [Factory](readme/factory.md)
- [Injection](readme/injection.md)
- [Arguments](readme/arguments.md)
- [Root arguments](readme/root-arguments.md)
- [Tags](readme/tags.md)
- [Multi-contract bindings](readme/multi-contract-bindings.md)
- [Field injection](readme/field-injection.md)
- [Method injection](readme/method-injection.md)
- [Property injection](readme/property-injection.md)
- [Default values](readme/default-values.md)
- [Required properties or fields](readme/required-properties-or-fields.md)
- [Tracking async disposable instances in delegates](readme/tracking-async-disposable-instances-in-delegates.md)
- [Tracking disposable instances in delegates](readme/tracking-disposable-instances-in-delegates.md)
- [Tracking disposable instances per a composition root](readme/tracking-disposable-instances-per-a-composition-root.md)
- [RootBind](readme/rootbind.md)
- [Tracking async disposable instances per a composition root](readme/tracking-async-disposable-instances-per-a-composition-root.md)
- [Root binding](readme/root-binding.md)
### Lifetimes
- [Singleton](readme/singleton.md)
- [PerResolve](readme/perresolve.md)
Expand Down Expand Up @@ -272,14 +264,17 @@ dotnet run
- [Check for a root](readme/check-for-a-root.md)
### Advanced
- [Composition root kinds](readme/composition-root-kinds.md)
- [Instance Initialization](readme/instance-initialization.md)
- [Tag Type](readme/tag-type.md)
- [Tag Unique](readme/tag-unique.md)
- [A few partial classes](readme/a-few-partial-classes.md)
- [Partial class](readme/partial-class.md)
- [Dependent compositions](readme/dependent-compositions.md)
- [Accumulators](readme/accumulators.md)
- [Global compositions](readme/global-compositions.md)
- [Tracking async disposable instances in delegates](readme/tracking-async-disposable-instances-in-delegates.md)
- [Tracking disposable instances in delegates](readme/tracking-disposable-instances-in-delegates.md)
- [Tracking disposable instances per a composition root](readme/tracking-disposable-instances-per-a-composition-root.md)
- [Tracking async disposable instances per a composition root](readme/tracking-async-disposable-instances-per-a-composition-root.md)
### Applications
- Console
- [Schrödinger's cat](readme/Console.md)
Expand Down Expand Up @@ -824,11 +819,6 @@ Then documentation for the composition root:
| Pure.DI.Templates | [![NuGet](https://buildstats.info/nuget/Pure.DI.Templates)](https://www.nuget.org/packages/Pure.DI.Templates) | Template Package you can call from the shell/command line. |
| Pure.DI.MS | [![NuGet](https://buildstats.info/nuget/Pure.DI.MS)](https://www.nuget.org/packages/Pure.DI.MS) | Tools for working with Microsoft DI |

## Requirements for development environments

- [.NET SDK 6.0.4xx or newer](https://dotnet.microsoft.com/download/dotnet/6.0)
- [C# 8 or newer](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80)

## Project template

Install the DI template [Pure.DI.Templates](https://www.nuget.org/packages/Pure.DI.Templates)
Expand Down
5 changes: 4 additions & 1 deletion build/ReadmeTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,10 @@ private static async Task AddExample(string logsDirectory, string exampleSearchP
.Replace("System.Collections.Generic.", "")
.Replace("System.", "")
.Replace("Pure.DI.", "")
.Replace(salt, "")));
.Replace(" Benchmarks.Model.", "")
.Replace(salt, "")
.Replace("(MethodImplOptions)0x100", "MethodImplOptions.AggressiveInlining")
.Replace("(MethodImplOptions)0x8", "MethodImplOptions.NoInlining")));
await examplesWriter.WriteLineAsync(generatedCode);
await examplesWriter.WriteLineAsync("```");
await examplesWriter.WriteLineAsync("");
Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

![](readme/di.gif)

## Usage requirements

Supports .NET starting with .NET Framework 2.0 released 2005-10-27 and all newer versions.

- Installed [.NET SDK 6.0.4](https://dotnet.microsoft.com/download/dotnet/6.0) or later
- Using [C# 8](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80) or later

## Key features

Pure.DI is not a framework or library, but a source code generator for creating object graphs. To make them accurate, the developer uses a set of intuitive hints from the Pure.DI API. During the compilation phase, Pure.DI determines the optimal graph structure, checks its correctness, and generates partial class code to create object graphs in the Pure DI paradigm using only basic language constructs. The resulting generated code is robust, works everywhere, throws no exceptions, does not depend on .NET library calls or .NET reflections, is efficient in terms of performance and memory consumption, and is subject to all optimizations. This code can be easily integrated into an application because it does not use unnecessary delegates, additional calls to any methods, type conversions, boxing/unboxing, etc.
Expand Down
22 changes: 11 additions & 11 deletions readme/ArrayDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,33 +100,33 @@ partial class Array
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
}

[MethodImpl((MethodImplOptions)0x100)]
public partial Benchmarks.Model.CompositionRoot TestPureDIByCR()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public partialCompositionRoot TestPureDIByCR()
{
return new Benchmarks.Model.CompositionRoot(new Benchmarks.Model.Service1(new Benchmarks.Model.Service2Array(new Benchmarks.Model.IService3[4] { new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v2(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v4(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()) })), new Benchmarks.Model.Service2Array(new Benchmarks.Model.IService3[4] { new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v2(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v4(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()) }), new Benchmarks.Model.Service2Array(new Benchmarks.Model.IService3[4] { new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v2(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v4(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()) }), new Benchmarks.Model.Service2Array(new Benchmarks.Model.IService3[4] { new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v2(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service3v4(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()) }), new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
return newCompositionRoot(newService1(newService2Array(newIService3[4] { newService3(newService4(), newService4()), newService3v2(newService4(), newService4()), newService3v3(newService4(), newService4()), newService3v4(newService4(), newService4()) })), newService2Array(newIService3[4] { newService3(newService4(), newService4()), newService3v2(newService4(), newService4()), newService3v3(newService4(), newService4()), newService3v4(newService4(), newService4()) }), newService2Array(newIService3[4] { newService3(newService4(), newService4()), newService3v2(newService4(), newService4()), newService3v3(newService4(), newService4()), newService3v4(newService4(), newService4()) }), newService2Array(newIService3[4] { newService3(newService4(), newService4()), newService3v2(newService4(), newService4()), newService3v3(newService4(), newService4()), newService3v4(newService4(), newService4()) }), newService3(newService4(), newService4()), newService4(), newService4());
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Resolve<T>()
{
return Resolver<T>.Value.Resolve(this);
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Resolve<T>(object? tag)
{
return Resolver<T>.Value.ResolveByTag(this, tag);
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type)
{
var index = (int)(_bucketSize * ((uint)RuntimeHelpers.GetHashCode(type) % 1));
ref var pair = ref _buckets[index];
return pair.Key == type ? pair.Value.Resolve(this) : Resolve(type, index);
}

[MethodImpl((MethodImplOptions)0x8)]
[MethodImpl(MethodImplOptions.NoInlining)]
private object Resolve(Type type, int index)
{
var finish = index + _bucketSize;
Expand All @@ -142,15 +142,15 @@ partial class Array
throw new InvalidOperationException($"{CannotResolveMessage} {OfTypeMessage} {type}.");
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type, object? tag)
{
var index = (int)(_bucketSize * ((uint)RuntimeHelpers.GetHashCode(type) % 1));
ref var pair = ref _buckets[index];
return pair.Key == type ? pair.Value.ResolveByTag(this, tag) : Resolve(type, tag, index);
}

[MethodImpl((MethodImplOptions)0x8)]
[MethodImpl(MethodImplOptions.NoInlining)]
private object Resolve(Type type, object? tag, int index)
{
var finish = index + _bucketSize;
Expand Down Expand Up @@ -281,12 +281,12 @@ partial class Array

private sealed class Resolver_0000: Resolver<Benchmarks.Model.CompositionRoot>
{
public override Benchmarks.Model.CompositionRoot Resolve(Array composition)
public overrideCompositionRoot Resolve(Array composition)
{
return composition.TestPureDIByCR();
}

public override Benchmarks.Model.CompositionRoot ResolveByTag(Array composition, object tag)
public overrideCompositionRoot ResolveByTag(Array composition, object tag)
{
switch (tag)
{
Expand Down
32 changes: 16 additions & 16 deletions readme/EnumDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,42 +100,42 @@ partial class Enum
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
}

[MethodImpl((MethodImplOptions)0x100)]
public partial Benchmarks.Model.CompositionRoot TestPureDIByCR()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public partialCompositionRoot TestPureDIByCR()
{
[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerable<Benchmarks.Model.IService3> EnumerationOf_perBlock10_IEnumerable()
{
yield return new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
yield return new Benchmarks.Model.Service3v2(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
yield return new Benchmarks.Model.Service3v3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
yield return new Benchmarks.Model.Service3v4(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
yield return newService3(newService4(), newService4());
yield return newService3v2(newService4(), newService4());
yield return newService3v3(newService4(), newService4());
yield return newService3v4(newService4(), newService4());
}
IEnumerable<Benchmarks.Model.IService3> perBlock10_IEnumerable = EnumerationOf_perBlock10_IEnumerable();
return new Benchmarks.Model.CompositionRoot(new Benchmarks.Model.Service1(new Benchmarks.Model.Service2Enum(perBlock10_IEnumerable)), new Benchmarks.Model.Service2Enum(perBlock10_IEnumerable), new Benchmarks.Model.Service2Enum(perBlock10_IEnumerable), new Benchmarks.Model.Service2Enum(perBlock10_IEnumerable), new Benchmarks.Model.Service3(new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4()), new Benchmarks.Model.Service4(), new Benchmarks.Model.Service4());
return newCompositionRoot(newService1(newService2Enum(perBlock10_IEnumerable)), newService2Enum(perBlock10_IEnumerable), newService2Enum(perBlock10_IEnumerable), newService2Enum(perBlock10_IEnumerable), newService3(newService4(), newService4()), newService4(), newService4());
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Resolve<T>()
{
return Resolver<T>.Value.Resolve(this);
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Resolve<T>(object? tag)
{
return Resolver<T>.Value.ResolveByTag(this, tag);
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type)
{
var index = (int)(_bucketSize * ((uint)RuntimeHelpers.GetHashCode(type) % 1));
ref var pair = ref _buckets[index];
return pair.Key == type ? pair.Value.Resolve(this) : Resolve(type, index);
}

[MethodImpl((MethodImplOptions)0x8)]
[MethodImpl(MethodImplOptions.NoInlining)]
private object Resolve(Type type, int index)
{
var finish = index + _bucketSize;
Expand All @@ -151,15 +151,15 @@ partial class Enum
throw new InvalidOperationException($"{CannotResolveMessage} {OfTypeMessage} {type}.");
}

[MethodImpl((MethodImplOptions)0x100)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type, object? tag)
{
var index = (int)(_bucketSize * ((uint)RuntimeHelpers.GetHashCode(type) % 1));
ref var pair = ref _buckets[index];
return pair.Key == type ? pair.Value.ResolveByTag(this, tag) : Resolve(type, tag, index);
}

[MethodImpl((MethodImplOptions)0x8)]
[MethodImpl(MethodImplOptions.NoInlining)]
private object Resolve(Type type, object? tag, int index)
{
var finish = index + _bucketSize;
Expand Down Expand Up @@ -290,12 +290,12 @@ partial class Enum

private sealed class Resolver_0000: Resolver<Benchmarks.Model.CompositionRoot>
{
public override Benchmarks.Model.CompositionRoot Resolve(Enum composition)
public overrideCompositionRoot Resolve(Enum composition)
{
return composition.TestPureDIByCR();
}

public override Benchmarks.Model.CompositionRoot ResolveByTag(Enum composition, object tag)
public overrideCompositionRoot ResolveByTag(Enum composition, object tag)
{
switch (tag)
{
Expand Down
5 changes: 0 additions & 5 deletions readme/FooterTemplate.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,11 +542,6 @@ Then documentation for the composition root:
| Pure.DI.Templates | [![NuGet](https://buildstats.info/nuget/Pure.DI.Templates)](https://www.nuget.org/packages/Pure.DI.Templates) | Template Package you can call from the shell/command line. |
| Pure.DI.MS | [![NuGet](https://buildstats.info/nuget/Pure.DI.MS)](https://www.nuget.org/packages/Pure.DI.MS) | Tools for working with Microsoft DI |

## Requirements for development environments

- [.NET SDK 6.0.4xx or newer](https://dotnet.microsoft.com/download/dotnet/6.0)
- [C# 8 or newer](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80)

## Project template

Install the DI template [Pure.DI.Templates](https://www.nuget.org/packages/Pure.DI.Templates)
Expand Down
Loading

0 comments on commit 10b0ead

Please sign in to comment.