Skip to content

Commit

Permalink
Special tags that allows injection on site
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Jun 21, 2024
1 parent 051a42e commit 46bcf66
Show file tree
Hide file tree
Showing 35 changed files with 2,479 additions and 24 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,20 @@ dotnet run
- [Composition root kinds](readme/composition-root-kinds.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)
- [Tag on injection site](readme/tag-on-injection-site.md)
- [Tag on a constructor argument](readme/tag-on-a-constructor-argument.md)
- [Tag on a member](readme/tag-on-a-member.md)
- [Tag on a method argument](readme/tag-on-a-method-argument.md)
- [Tag on injection site with wildcards](readme/tag-on-injection-site-with-wildcards.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)
- [Partial class](readme/partial-class.md)
- [A few partial classes](readme/a-few-partial-classes.md)
- [Tracking disposable instances per a composition root](readme/tracking-disposable-instances-per-a-composition-root.md)
- [Tracking disposable instances in delegates](readme/tracking-disposable-instances-in-delegates.md)
- [Tracking async disposable instances per a composition root](readme/tracking-async-disposable-instances-per-a-composition-root.md)
- [Tracking async disposable instances in delegates](readme/tracking-async-disposable-instances-in-delegates.md)
### Applications
- Console
- [Schrödinger's cat](readme/Console.md)
Expand Down
60 changes: 60 additions & 0 deletions readme/tag-on-a-constructor-argument.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#### Tag on a constructor argument

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

The wildcards ‘*’ and ‘?’ are supported.


```c#
namespace Pure.DI.UsageTests.Advanced.OnConstructorArgScenario;


interface IDependency;

class AbcDependency : IDependency;

class XyzDependency : IDependency;

class Consumer<T>(IDependency myDep)
{
public IDependency Dependency { get; } = myDep;
}

interface IService
{
IDependency Dependency1 { get; }

IDependency Dependency2 { get; }
}

class Service(
IDependency dependency1,
Consumer<string> consumer)
: IService
{
public IDependency Dependency1 { get; } = dependency1;

public IDependency Dependency2 => consumer.Dependency;
}

DI.Setup(nameof(Composition))
.Bind(Tag.OnConstructorArg<Service>("dependency1"))
.To<AbcDependency>()
.Bind(Tag.OnConstructorArg<Consumer<TT>>("myDep"))
.To<XyzDependency>()
.Bind<IService>().To<Service>()

// Specifies to create the composition root named "Root"
.Root<IService>("Root");

var composition = new Composition();
var service = composition.Root;
service.Dependency1.ShouldBeOfType<AbcDependency>();
service.Dependency2.ShouldBeOfType<XyzDependency>();
```

> [!WARNING]
> Each potentially injectable argument, property, or field contains an additional tag. This tag can be used to specify what can be injected there. This will only work if the binding type and the tag match. So while this approach can be useful for specifying what to enter, it can be more expensive to maintain and less reliable, so it is recommended to use attributes like `[Tag(...)]` instead.


102 changes: 102 additions & 0 deletions readme/tag-on-a-member.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#### Tag on a member

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

The wildcards ‘*’ and ‘?’ are supported.


```c#
namespace Pure.DI.UsageTests.Advanced.TagOnMemberScenario;


interface IDependency;

class AbcDependency : IDependency;

class XyzDependency : IDependency;

interface IService
{
IDependency Dependency { get; }
}

class Service : IService
{
public required IDependency Dependency { init; get; }
}

DI.Setup(nameof(Composition))
.Bind().To<AbcDependency>()
.Bind(Tag.OnMember<Service>(nameof(Service.Dependency)))
.To<XyzDependency>()
.Bind<IService>().To<Service>()

// Specifies to create the composition root named "Root"
.Root<IService>("Root");

var composition = new Composition();
var service = composition.Root;
service.Dependency.ShouldBeOfType<XyzDependency>();
```

> [!WARNING]
> Each potentially injectable argument, property, or field contains an additional tag. This tag can be used to specify what can be injected there. This will only work if the binding type and the tag match. So while this approach can be useful for specifying what to enter, it can be more expensive to maintain and less reliable, so it is recommended to use attributes like `[Tag(...)]` instead.
The following partial class will be generated:

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

public Composition()
{
_root = this;
}

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

public IService Root
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return new Service()
{
Dependency = new XyzDependency()
};
}
}
}
```

Class diagram:

```mermaid
classDiagram
class Composition {
<<partial>>
+IService Root
}
XyzDependency --|> IDependency
class XyzDependency {
+XyzDependency()
}
Service --|> IService
class Service {
+Service()
+IDependency Dependency
}
class IDependency {
<<interface>>
}
class IService {
<<interface>>
}
Composition ..> Service : IService Root
Service *-- XyzDependency : IDependency
```

105 changes: 105 additions & 0 deletions readme/tag-on-a-method-argument.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#### Tag on a method argument

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

The wildcards ‘*’ and ‘?’ are supported.


```c#
namespace Pure.DI.UsageTests.Advanced.TagOnMethodArgScenario;


interface IDependency;

class AbcDependency : IDependency;

class XyzDependency : IDependency;

interface IService
{
IDependency? Dependency { get; }
}

class Service : IService
{
[Ordinal(1)]
public void Initialize(IDependency dep) =>
Dependency = dep;

public IDependency? Dependency { get; private set; }
}

DI.Setup(nameof(Composition))
.Bind().To<AbcDependency>()
.Bind(Tag.OnMethodArg<Service>(nameof(Service.Initialize), "dep"))
.To<XyzDependency>()
.Bind<IService>().To<Service>()

// Specifies to create the composition root named "Root"
.Root<IService>("Root");

var composition = new Composition();
var service = composition.Root;
service.Dependency.ShouldBeOfType<XyzDependency>();
```

> [!WARNING]
> Each potentially injectable argument, property, or field contains an additional tag. This tag can be used to specify what can be injected there. This will only work if the binding type and the tag match. So while this approach can be useful for specifying what to enter, it can be more expensive to maintain and less reliable, so it is recommended to use attributes like `[Tag(...)]` instead.
The following partial class will be generated:

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

public Composition()
{
_root = this;
}

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

public IService Root
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
Service transientService0 = new Service();
transientService0.Initialize(new XyzDependency());
return transientService0;
}
}
}
```

Class diagram:

```mermaid
classDiagram
class Composition {
<<partial>>
+IService Root
}
XyzDependency --|> IDependency
class XyzDependency {
+XyzDependency()
}
Service --|> IService
class Service {
+Service()
+Initialize(IDependency dep) : Void
}
class IDependency {
<<interface>>
}
class IService {
<<interface>>
}
Composition ..> Service : IService Root
Service *-- XyzDependency : IDependency
```

Loading

0 comments on commit 46bcf66

Please sign in to comment.