Skip to content

Commit

Permalink
Improved root arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Jan 25, 2025
1 parent 6066fbf commit b48b5d1
Show file tree
Hide file tree
Showing 33 changed files with 400 additions and 204 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ dotnet run
- [Smart tags](readme/smart-tags.md)
- [Build up of an existing object](readme/build-up-of-an-existing-object.md)
- [Builders](readme/builders.md)
- [Builders with arguments](readme/builders-with-arguments.md)
- [Field injection](readme/field-injection.md)
- [Method injection](readme/method-injection.md)
- [Property injection](readme/property-injection.md)
Expand Down
4 changes: 2 additions & 2 deletions readme/async-disposable-scope.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ partial class Composition: IDisposable, IAsyncDisposable
() =>
{
Composition transientComposition3 = this;
Session localValue93 = new Session(transientComposition3);
return localValue93;
Session localValue92 = new Session(transientComposition3);
return localValue92;
});
return new Program(perBlockFunc1);
}
Expand Down
10 changes: 5 additions & 5 deletions readme/auto-scoped.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ partial class Composition
{
Composition transientComposition3 = this;
IService transientIService2;
Composition localBaseComposition95 = transientComposition3;
Composition localBaseComposition94 = transientComposition3;
// Creates a session
var localSession96 = new Composition(localBaseComposition95);
var localSession95 = new Composition(localBaseComposition94);
// Provides a root
transientIService2 = localSession96.SessionRoot;
IService localValue94 = transientIService2;
return localValue94;
transientIService2 = localSession95.SessionRoot;
IService localValue93 = transientIService2;
return localValue93;
});
return new Program(perBlockFunc1);
}
Expand Down
9 changes: 5 additions & 4 deletions readme/build-up-of-an-existing-generic-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,13 @@ partial class Composition
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IService<Guid> GetMyService(string name)
{
if (Object.ReferenceEquals(name, null)) throw new ArgumentNullException(nameof(name));
Guid transientGuid2 = Guid.NewGuid();
Dependency<Guid> transientDependency1;
Dependency<Guid> localDependency56 = new Dependency<Guid>();
localDependency56.Name = name;
localDependency56.SetId(transientGuid2);
transientDependency1 = localDependency56;
Dependency<Guid> localDependency55 = new Dependency<Guid>();
localDependency55.Name = name;
localDependency55.SetId(transientGuid2);
transientDependency1 = localDependency55;
return new Service<Guid>(transientDependency1);
}
}
Expand Down
9 changes: 5 additions & 4 deletions readme/build-up-of-an-existing-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,13 @@ partial class Composition
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IService GetMyService(string name)
{
if (Object.ReferenceEquals(name, null)) throw new ArgumentNullException(nameof(name));
Guid transientGuid2 = Guid.NewGuid();
Dependency transientDependency1;
var localDependency50 = new Dependency();
localDependency50.Name = name;
localDependency50.SetId(transientGuid2);
transientDependency1 = localDependency50;
var localDependency49 = new Dependency();
localDependency49.Name = name;
localDependency49.SetId(transientGuid2);
transientDependency1 = localDependency49;
return new Service(transientDependency1);
}
}
Expand Down
190 changes: 190 additions & 0 deletions readme/builders-with-arguments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#### Builders with arguments

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

Builders can be used with arguments as in the example below:


```c#
using Shouldly;
using Pure.DI;

DI.Setup(nameof(Composition))
.RootArg<Guid>("serviceId")
.Bind().To<Dependency>()
// Service builder
.Builder<Service>("BuildUp");

var composition = new Composition();

var id = Guid.NewGuid();
var service = composition.BuildUp(new Service(), id);
service.Id.ShouldBe(id);
service.Dependency.ShouldBeOfType<Dependency>();

interface IDependency;

class Dependency : IDependency;

interface IService
{
Guid Id { get; }

IDependency? Dependency { get; }
}

record Service: IService
{
public Guid Id { get; private set; } = Guid.Empty;

// The Dependency attribute specifies to perform an injection
[Dependency]
public IDependency? Dependency { get; set; }

// The Dependency attribute specifies to perform an injection
[Dependency]
public void SetId(Guid id) => Id = id;
}
```

<details>
<summary>Running this code sample locally</summary>

- Make sure you have the [.NET SDK 9.0](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) or later is installed
```bash
dotnet --list-sdk
```
- Create a net9.0 (or later) console application
```bash
dotnet new console -n Sample
```
- Add references to NuGet packages
- [Pure.DI](https://www.nuget.org/packages/Pure.DI)
- [Shouldly](https://www.nuget.org/packages/Shouldly)
```bash
dotnet add package Pure.DI
dotnet add package Shouldly
```
- Copy the example code into the _Program.cs_ file

You are ready to run the example 🚀
```bash
dotnet run
```

</details>

The following partial class will be generated:

```c#
partial class Composition
{
private readonly Composition _root;

[OrdinalAttribute(128)]
public Composition()
{
_root = this;
}

internal Composition(Composition parentScope)
{
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Service BuildUp(Service instance, Guid serviceId)
{
if (Object.ReferenceEquals(instance, null)) throw new ArgumentNullException(nameof(instance));
Service transientService0;
Service localInstance48 = instance;
localInstance48.Dependency = new Dependency();
localInstance48.SetId(serviceId);
transientService0 = localInstance48;
return transientService0;
}

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

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

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type)
{
throw new InvalidOperationException($"{CannotResolveMessage} {OfTypeMessage} {type}.");
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public object Resolve(Type type, object? tag)
{
throw new InvalidOperationException($"{CannotResolveMessage} \"{tag}\" {OfTypeMessage} {type}.");
}

private const string CannotResolveMessage = "Cannot resolve composition root ";
private const string OfTypeMessage = "of type ";

private class Resolver<T>: IResolver<Composition, T>
{
public static IResolver<Composition, T> Value = new Resolver<T>();

public virtual T Resolve(Composition composite)
{
throw new InvalidOperationException($"{CannotResolveMessage}{OfTypeMessage}{typeof(T)}.");
}

public virtual T ResolveByTag(Composition composite, object tag)
{
throw new InvalidOperationException($"{CannotResolveMessage}\"{tag}\" {OfTypeMessage}{typeof(T)}.");
}
}
}
```

Class diagram:

```mermaid
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
Dependency --|> IDependency
Composition ..> Service : Service BuildUp(Pure.DI.UsageTests.Basics.BuilderWithArgumentsScenario.Service instance, System.Guid serviceId)
Service o-- Service : "2M01D25di" Argument "instance"
Service *-- Dependency : IDependency
Service o-- Guid : Argument "serviceId"
namespace Pure.DI.UsageTests.Basics.BuilderWithArgumentsScenario {
class Composition {
<<partial>>
+Service BuildUp(Pure.DI.UsageTests.Basics.BuilderWithArgumentsScenario.Service instance, System.Guid serviceId)
+ T ResolveᐸTᐳ()
+ T ResolveᐸTᐳ(object? tag)
+ object Resolve(Type type)
+ object Resolve(Type type, object? tag)
}
class Dependency {
+Dependency()
}
class IDependency {
<<interface>>
}
class Service {
<<record>>
}
}
namespace System {
class Guid {
<<struct>>
}
}
```

Loading

0 comments on commit b48b5d1

Please sign in to comment.