Skip to content

Commit 3744a92

Browse files
Update README.md
1 parent 3f5e36c commit 3744a92

35 files changed

+956
-127
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,10 @@ dotnet run
204204
- [Tags](readme/tags.md)
205205
- [Smart tags](readme/smart-tags.md)
206206
- [Build up of an existing object](readme/build-up-of-an-existing-object.md)
207+
- [Builder](readme/builder.md)
208+
- [Builder with arguments](readme/builder-with-arguments.md)
207209
- [Builders](readme/builders.md)
208-
- [Builders with arguments](readme/builders-with-arguments.md)
210+
- [Builders with a name template](readme/builders-with-a-name-template.md)
209211
- [Field injection](readme/field-injection.md)
210212
- [Method injection](readme/method-injection.md)
211213
- [Property injection](readme/property-injection.md)
@@ -214,6 +216,7 @@ dotnet run
214216
- [Root binding](readme/root-binding.md)
215217
- [Async Root](readme/async-root.md)
216218
- [Consumer types](readme/consumer-types.md)
219+
- [Roots](readme/roots.md)
217220
### Lifetimes
218221
- [Transient](readme/transient.md)
219222
- [Singleton](readme/singleton.md)
@@ -257,7 +260,7 @@ dotnet run
257260
- [Build up of an existing generic object](readme/build-up-of-an-existing-generic-object.md)
258261
- [Generic root arguments](readme/generic-root-arguments.md)
259262
- [Complex generic root arguments](readme/complex-generic-root-arguments.md)
260-
- [Generic builders](readme/generic-builders.md)
263+
- [Generic builder](readme/generic-builder.md)
261264
### Attributes
262265
- [Constructor ordinal attribute](readme/constructor-ordinal-attribute.md)
263266
- [Dependency attribute](readme/dependency-attribute.md)
@@ -288,6 +291,7 @@ dotnet run
288291
- [Check for a root](readme/check-for-a-root.md)
289292
### Advanced
290293
- [Composition root kinds](readme/composition-root-kinds.md)
294+
- [Root with mame template](readme/root-with-mame-template.md)
291295
- [Tag Type](readme/tag-type.md)
292296
- [Tag Unique](readme/tag-unique.md)
293297
- [Tag on injection site](readme/tag-on-injection-site.md)
@@ -315,6 +319,7 @@ dotnet run
315319
- [DI tracing via serilog](readme/di-tracing-via-serilog.md)
316320
### Unity
317321
- [Basic Unity use case](readme/basic-unity-use-case.md)
322+
- [Unity MonoBehaviours](readme/unity-monobehaviours.md)
318323
### Applications
319324
- Console
320325
- [Schrödinger's cat](readme/Console.md)

readme/WebAPI.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Composition setup file is [Composition.cs](/samples/WebAPI/Composition.cs):
88

99
```c#
1010
using Pure.DI;
11+
using Controllers;
12+
using Microsoft.AspNetCore.Mvc;
13+
using Pure.DI.MS;
14+
using WeatherForecast;
1115
using static Pure.DI.Lifetime;
1216

1317
internal partial class Composition: ServiceProviderFactory<Composition>
@@ -16,8 +20,8 @@ internal partial class Composition: ServiceProviderFactory<Composition>
1620
// Use the DI setup from the base class
1721
.DependsOn(Base)
1822
.Bind().As(Singleton).To<WeatherForecastService>()
19-
// Provides the composition root for Weather Forecast controller
20-
.Root<WeatherForecastController>();
23+
// Provides controllers as roots
24+
.Roots<ControllerBase>();
2125
}
2226
```
2327

readme/WebApp.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Composition setup file is [Composition.cs](/samples/WebApp/Composition.cs):
88

99
```c#
1010
using Pure.DI;
11+
using Pure.DI.MS;
12+
using Controllers;
13+
using Microsoft.AspNetCore.Mvc;
14+
using WeatherForecast;
1115
using static Pure.DI.Lifetime;
1216

1317
internal partial class Composition: ServiceProviderFactory<Composition>
@@ -16,8 +20,8 @@ internal partial class Composition: ServiceProviderFactory<Composition>
1620
// Use the DI setup from the base class
1721
.DependsOn(Base)
1822
.Bind().As(Singleton).To<WeatherForecastService>()
19-
// Provides the composition root for Home controller
20-
.Root<HomeController>();
23+
// Provides controllers as roots
24+
.Roots<Controller>();
2125
}
2226
```
2327

readme/async-disposable-scope.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ partial class Composition: IDisposable, IAsyncDisposable
172172
() =>
173173
{
174174
Composition transientComposition3 = this;
175-
Session localValue92 = new Session(transientComposition3);
176-
return localValue92;
175+
Session localValue96 = new Session(transientComposition3);
176+
return localValue96;
177177
});
178178
return new Program(perBlockFunc1);
179179
}

readme/auto-scoped.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ partial class Composition
129129
{
130130
Composition transientComposition3 = this;
131131
IService transientIService2;
132-
Composition localBaseComposition94 = transientComposition3;
132+
Composition localBaseComposition98 = transientComposition3;
133133
// Creates a session
134-
var localSession95 = new Composition(localBaseComposition94);
134+
var localSession99 = new Composition(localBaseComposition98);
135135
// Provides a root
136-
transientIService2 = localSession95.SessionRoot;
137-
IService localValue93 = transientIService2;
138-
return localValue93;
136+
transientIService2 = localSession99.SessionRoot;
137+
IService localValue97 = transientIService2;
138+
return localValue97;
139139
});
140140
return new Program(perBlockFunc1);
141141
}

readme/basic-unity-use-case.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ partial class Composition
130130
}
131131

132132
Clock transientClock0;
133-
Clock localBuildingInstance97 = buildingInstance;
134-
localBuildingInstance97.ClockService = _root._singletonClockService43;
135-
transientClock0 = localBuildingInstance97;
133+
Clock localBuildingInstance104 = buildingInstance;
134+
localBuildingInstance104.ClockService = _root._singletonClockService43;
135+
transientClock0 = localBuildingInstance104;
136136
return transientClock0;
137137
}
138138
}

readme/build-up-of-an-existing-generic-object.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ partial class Composition
111111
if (name is null) throw new ArgumentNullException(nameof(name));
112112
Guid transientGuid2 = Guid.NewGuid();
113113
Dependency<Guid> transientDependency1;
114-
Dependency<Guid> localDependency55 = new Dependency<Guid>();
115-
localDependency55.Name = name;
116-
localDependency55.SetId(transientGuid2);
117-
transientDependency1 = localDependency55;
114+
Dependency<Guid> localDependency59 = new Dependency<Guid>();
115+
localDependency59.Name = name;
116+
localDependency59.SetId(transientGuid2);
117+
transientDependency1 = localDependency59;
118118
return new Service<Guid>(transientDependency1);
119119
}
120120
}

readme/build-up-of-an-existing-object.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ partial class Composition
107107
if (name is null) throw new ArgumentNullException(nameof(name));
108108
Guid transientGuid2 = Guid.NewGuid();
109109
Dependency transientDependency1;
110-
var localDependency49 = new Dependency();
111-
localDependency49.Name = name;
112-
localDependency49.SetId(transientGuid2);
113-
transientDependency1 = localDependency49;
110+
var localDependency53 = new Dependency();
111+
localDependency53.Name = name;
112+
localDependency53.SetId(transientGuid2);
113+
transientDependency1 = localDependency53;
114114
return new Service(transientDependency1);
115115
}
116116
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#### Builders with arguments
1+
#### Builder with arguments
22

33
[![CSharp](https://img.shields.io/badge/C%23-code-blue.svg)](../tests/Pure.DI.UsageTests/Basics/BuilderWithArgumentsScenario.cs)
44

@@ -97,10 +97,10 @@ partial class Composition
9797
{
9898
if (buildingInstance is null) throw new ArgumentNullException(nameof(buildingInstance));
9999
Service transientService0;
100-
Service localBuildingInstance48 = buildingInstance;
101-
localBuildingInstance48.Dependency = new Dependency();
102-
localBuildingInstance48.SetId(serviceId);
103-
transientService0 = localBuildingInstance48;
100+
Service localBuildingInstance52 = buildingInstance;
101+
localBuildingInstance52.Dependency = new Dependency();
102+
localBuildingInstance52.SetId(serviceId);
103+
transientService0 = localBuildingInstance52;
104104
return transientService0;
105105
}
106106

readme/builder.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#### Builder
2+
3+
[![CSharp](https://img.shields.io/badge/C%23-code-blue.svg)](../tests/Pure.DI.UsageTests/Basics/BuilderScenario.cs)
4+
5+
Sometimes you need to build up an existing composition root and inject all of its dependencies, in which case the `Builder` method will be useful, as in the example below:
6+
7+
8+
```c#
9+
using Shouldly;
10+
using Pure.DI;
11+
12+
DI.Setup(nameof(Composition))
13+
.Bind().To(_ => Guid.NewGuid())
14+
.Bind().To<Dependency>()
15+
.Builder<Service>("BuildUpService");
16+
17+
var composition = new Composition();
18+
19+
var service = composition.BuildUpService(new Service());
20+
service.Id.ShouldNotBe(Guid.Empty);
21+
service.Dependency.ShouldBeOfType<Dependency>();
22+
23+
interface IDependency;
24+
25+
class Dependency : IDependency;
26+
27+
interface IService
28+
{
29+
Guid Id { get; }
30+
31+
IDependency? Dependency { get; }
32+
}
33+
34+
record Service: IService
35+
{
36+
public Guid Id { get; private set; } = Guid.Empty;
37+
38+
// The Dependency attribute specifies to perform an injection
39+
[Dependency]
40+
public IDependency? Dependency { get; set; }
41+
42+
[Dependency]
43+
public void SetId(Guid id) => Id = id;
44+
}
45+
```
46+
47+
<details>
48+
<summary>Running this code sample locally</summary>
49+
50+
- Make sure you have the [.NET SDK 9.0](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) or later is installed
51+
```bash
52+
dotnet --list-sdk
53+
```
54+
- Create a net9.0 (or later) console application
55+
```bash
56+
dotnet new console -n Sample
57+
```
58+
- Add references to NuGet packages
59+
- [Pure.DI](https://www.nuget.org/packages/Pure.DI)
60+
- [Shouldly](https://www.nuget.org/packages/Shouldly)
61+
```bash
62+
dotnet add package Pure.DI
63+
dotnet add package Shouldly
64+
```
65+
- Copy the example code into the _Program.cs_ file
66+
67+
You are ready to run the example 🚀
68+
```bash
69+
dotnet run
70+
```
71+
72+
</details>
73+
74+
The default builder method name is `BuildUp`. The first argument to this method will always be the instance to be built.
75+
76+
The following partial class will be generated:
77+
78+
```c#
79+
partial class Composition
80+
{
81+
private readonly Composition _root;
82+
83+
[OrdinalAttribute(128)]
84+
public Composition()
85+
{
86+
_root = this;
87+
}
88+
89+
internal Composition(Composition parentScope)
90+
{
91+
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
92+
}
93+
94+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
95+
public Service BuildUpService(Service buildingInstance)
96+
{
97+
if (buildingInstance is null) throw new ArgumentNullException(nameof(buildingInstance));
98+
Guid transientGuid2 = Guid.NewGuid();
99+
Service transientService0;
100+
Service localBuildingInstance47 = buildingInstance;
101+
localBuildingInstance47.Dependency = new Dependency();
102+
localBuildingInstance47.SetId(transientGuid2);
103+
transientService0 = localBuildingInstance47;
104+
return transientService0;
105+
}
106+
107+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
108+
public T Resolve<T>()
109+
{
110+
return Resolver<T>.Value.Resolve(this);
111+
}
112+
113+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
114+
public T Resolve<T>(object? tag)
115+
{
116+
return Resolver<T>.Value.ResolveByTag(this, tag);
117+
}
118+
119+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
120+
public object Resolve(Type type)
121+
{
122+
throw new InvalidOperationException($"{CannotResolveMessage} {OfTypeMessage} {type}.");
123+
}
124+
125+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
126+
public object Resolve(Type type, object? tag)
127+
{
128+
throw new InvalidOperationException($"{CannotResolveMessage} \"{tag}\" {OfTypeMessage} {type}.");
129+
}
130+
131+
private const string CannotResolveMessage = "Cannot resolve composition root ";
132+
private const string OfTypeMessage = "of type ";
133+
134+
private class Resolver<T>: IResolver<Composition, T>
135+
{
136+
public static IResolver<Composition, T> Value = new Resolver<T>();
137+
138+
public virtual T Resolve(Composition composite)
139+
{
140+
throw new InvalidOperationException($"{CannotResolveMessage}{OfTypeMessage}{typeof(T)}.");
141+
}
142+
143+
public virtual T ResolveByTag(Composition composite, object tag)
144+
{
145+
throw new InvalidOperationException($"{CannotResolveMessage}\"{tag}\" {OfTypeMessage}{typeof(T)}.");
146+
}
147+
}
148+
}
149+
```
150+
151+
Class diagram:
152+
153+
```mermaid
154+
---
155+
config:
156+
class:
157+
hideEmptyMembersBox: true
158+
---
159+
classDiagram
160+
Dependency --|> IDependency
161+
Composition ..> Service : Service BuildUpService(Pure.DI.UsageTests.Basics.BuilderScenario.Service buildingInstance)
162+
Service *-- Dependency : IDependency
163+
Service *-- Guid : Guid
164+
namespace Pure.DI.UsageTests.Basics.BuilderScenario {
165+
class Composition {
166+
<<partial>>
167+
+Service BuildUpService(Pure.DI.UsageTests.Basics.BuilderScenario.Service buildingInstance)
168+
+ T ResolveᐸTᐳ()
169+
+ T ResolveᐸTᐳ(object? tag)
170+
+ object Resolve(Type type)
171+
+ object Resolve(Type type, object? tag)
172+
}
173+
class Dependency {
174+
+Dependency()
175+
}
176+
class IDependency {
177+
<<interface>>
178+
}
179+
class Service {
180+
<<record>>
181+
}
182+
}
183+
namespace System {
184+
class Guid {
185+
<<struct>>
186+
}
187+
}
188+
```
189+

0 commit comments

Comments
 (0)