Skip to content

Commit

Permalink
Add TypeInformation accessible for factories
Browse files Browse the repository at this point in the history
  • Loading branch information
z4kn4fein committed Jun 13, 2023
1 parent 433c672 commit b6f64ef
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.10.1
5.10.2
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v5.10.2] - 2023-06-13
### Added
- Access to the actual `TypeInformation` as a factory delegate input parameter. The `TypeInformation` holds every reflected context information about the currently resolving type. This can be useful when the resolution is, e.g., in an open generic context, and we want to know which closed generic variant is requested.
```cs
container.Register(typeof(IService<>), options => options.WithFactory<TypeInformation>(typeInfo => /* typeInfo.Type holds the currently resolving closed generic type */));
```

## [v5.10.1] - 2023-06-09
### Added
- `ParentDependency` flag for `ResolutionBehavior`. It indicates that parent containers (including indirect all ancestors) can only provide dependencies for services that are already selected for resolution.
Expand Down Expand Up @@ -47,14 +54,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

For an example class like `class Sample : ISample1, ISample2 { }` the registration mapping looked like this:

```
```cs
ISample1 => NewRegistrationOf(Sample)
ISample2 => NewRegistrationOf(Sample)
```

Now each interface/base type is mapped to the same registration:

```
```cs
registration = NewRegistrationOf(Sample)
ISample1 => registration
ISample2 => registration
Expand Down Expand Up @@ -373,6 +380,7 @@ The validation was executed only at the expression tree building phase, so an al
- Removed the legacy container extension functionality.
- Removed the support of PCL v259.

[v5.10.2]: https://github.com/z4kn4fein/stashbox/compare/5.10.1...5.10.2
[v5.10.1]: https://github.com/z4kn4fein/stashbox/compare/5.10.0...5.10.1
[v5.10.0]: https://github.com/z4kn4fein/stashbox/compare/5.9.1...5.10.0
[v5.9.1]: https://github.com/z4kn4fein/stashbox/compare/5.9.0...5.9.1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Stashbox is a lightweight, fast, and portable dependency injection framework for

Github (stable) | NuGet (stable) | Fuget (stable) | NuGet (pre-release)
--- | --- |---------------------------------------------------------------------------------------------------------------------------------| ---
[![Github release](https://img.shields.io/github/release/z4kn4fein/stashbox.svg)](https://github.com/z4kn4fein/stashbox/releases) | [![NuGet Version](https://buildstats.info/nuget/Stashbox)](https://www.nuget.org/packages/Stashbox/) | [![Stashbox on fuget.org](https://www.fuget.org/packages/Stashbox/badge.svg?v=5.10.1)](https://www.fuget.org/packages/Stashbox) | [![Nuget pre-release](https://img.shields.io/nuget/vpre/Stashbox)](https://www.nuget.org/packages/Stashbox/)
[![Github release](https://img.shields.io/github/release/z4kn4fein/stashbox.svg)](https://github.com/z4kn4fein/stashbox/releases) | [![NuGet Version](https://buildstats.info/nuget/Stashbox)](https://www.nuget.org/packages/Stashbox/) | [![Stashbox on fuget.org](https://www.fuget.org/packages/Stashbox/badge.svg?v=5.10.2)](https://www.fuget.org/packages/Stashbox) | [![Nuget pre-release](https://img.shields.io/nuget/vpre/Stashbox)](https://www.nuget.org/packages/Stashbox/)

## Core Attributes
- 🚀 Fast, thread-safe, and lock-free operations.
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/getting-started/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ Stashbox and its extensions are distributed via [NuGet](https://www.nuget.org/pa

You can install the package by typing the following into the Package Manager Console:
```powershell
Install-Package Stashbox -Version 5.10.1
Install-Package Stashbox -Version 5.10.2
```

</TabItem>
<TabItem value="dotnet CLI" label="dotnet CLI">

You can install the package by using the dotnet cli:
```bash
dotnet add package Stashbox --version 5.10.1
dotnet add package Stashbox --version 5.10.2
```

</TabItem>
<TabItem value="PackageReference" label="PackageReference">

You can add the package into the package references of your `.csproj`:
```xml
<PackageReference Include="Stashbox" Version="5.10.1" />
<PackageReference Include="Stashbox" Version="5.10.2" />
```

</TabItem>
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ These are the latest available stable and pre-release versions:

Github (stable) | NuGet (stable) | Fuget (stable) | NuGet (daily)
--- | --- |---------------------------------------------------------------------------------------------------------------------------------| ---
[![Github release](https://img.shields.io/github/release/z4kn4fein/stashbox.svg)](https://github.com/z4kn4fein/stashbox/releases) | [![NuGet Version](https://buildstats.info/nuget/Stashbox)](https://www.nuget.org/packages/Stashbox/) | [![Stashbox on fuget.org](https://www.fuget.org/packages/Stashbox/badge.svg?v=5.10.1)](https://www.fuget.org/packages/Stashbox) | [![Nuget pre-release](https://img.shields.io/nuget/vpre/Stashbox)](https://www.nuget.org/packages/Stashbox/)
[![Github release](https://img.shields.io/github/release/z4kn4fein/stashbox.svg)](https://github.com/z4kn4fein/stashbox/releases) | [![NuGet Version](https://buildstats.info/nuget/Stashbox)](https://www.nuget.org/packages/Stashbox/) | [![Stashbox on fuget.org](https://www.fuget.org/packages/Stashbox/badge.svg?v=5.10.2)](https://www.fuget.org/packages/Stashbox) | [![Nuget pre-release](https://img.shields.io/nuget/vpre/Stashbox)](https://www.nuget.org/packages/Stashbox/)

## Core attributes
- 🚀 Fast, thread-safe, and lock-free operations.
Expand Down
32 changes: 32 additions & 0 deletions docs/docs/guides/advanced-registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,38 @@ IEventProcessor processor = container.Resolve<IEventProcessor>();
</div>
</CodeDescPanel>

<CodeDescPanel>
<div>

### Accessing the currently resolving type in factories

To access the currently resolving type in factory delegates, you can set the `TypeInformation` type as an input parameter of the factory.
The `TypeInformation` holds every reflected context information about the currently resolving type.

This can be useful when the resolution is, e.g., in an open generic context, and we want to know which closed generic variant is requested.

</div>
<div>


```cs
interface IService<T> { }

class Service<T> : IService<T> { }

container.Register(typeof(IService<>), typeof(Service<>), options =>
options.WithFactory<TypeInformation>(typeInfo =>
{
// typeInfo.Type here holds the actual type like
// IService<int> based on the resolution request below.
}));

container.Resolve<IService<int>>();
```

</div>
</CodeDescPanel>


## Multiple implementations

Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function HomepageHeader() {

<div className={styles.installContainer}>
<div className={styles.install}>
<pre><span className={styles.command_start}>{'$'} </span><span className={styles.command}>dotnet</span><span> add package Stashbox</span><span className={styles.options}> --version</span> 5.10.1<span className={styles.cursor}></span></pre>
<pre><span className={styles.command_start}>{'$'} </span><span className={styles.command}>dotnet</span><span> add package Stashbox</span><span className={styles.options}> --version</span> 5.10.2<span className={styles.cursor}></span></pre>
</div>
</div>

Expand Down
17 changes: 13 additions & 4 deletions src/Expressions/ExpressionBuilder.Factory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Stashbox.Utils;

namespace Stashbox.Expressions;

Expand All @@ -16,7 +17,7 @@ private static Expression GetExpressionForFactory(ServiceRegistration serviceReg

resolutionContext.CircularDependencyBarrier.Add(serviceRegistration.RegistrationId);

var parameters = GetFactoryParameters(factoryOptions, resolutionContext);
var parameters = GetFactoryParameters(factoryOptions, resolutionContext, typeInformation);
var expression = ConstructFactoryExpression(factoryOptions, parameters);
var result = ExpressionFactory.ConstructBuildUpExpression(serviceRegistration, resolutionContext, expression, typeInformation);

Expand All @@ -35,13 +36,21 @@ private static Expression ConstructFactoryExpression(FactoryOptions factoryOptio
: method.CallMethod(factoryOptions.Factory.Target.AsConstant(), parameters);
}

private static IEnumerable<Expression> GetFactoryParameters(FactoryOptions factoryOptions, ResolutionContext resolutionContext)
private static IEnumerable<Expression> GetFactoryParameters(FactoryOptions factoryOptions, ResolutionContext resolutionContext, TypeInformation typeInformation)
{
var length = factoryOptions.FactoryParameters.Length;
for (var i = 0; i < length - 1; i++)
{
var typeInfo = new TypeInformation(factoryOptions.FactoryParameters[i], null);
yield return resolutionContext.CurrentContainerContext.ResolutionStrategy.BuildExpressionForType(resolutionContext, typeInfo).ServiceExpression;
var type = factoryOptions.FactoryParameters[i];
if (type == TypeCache<TypeInformation>.Type)
{
yield return typeInformation.AsConstant();
}
else
{
var typeInfo = new TypeInformation(factoryOptions.FactoryParameters[i], null);
yield return resolutionContext.CurrentContainerContext.ResolutionStrategy.BuildExpressionForType(resolutionContext, typeInfo).ServiceExpression;
}
}
}
}
13 changes: 13 additions & 0 deletions test/FactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,19 @@ public void FactoryTests_Resolve_Action_Without_Implementation_Unknown_Open_Gene
Assert.IsType<TG<int>>(container2.Resolve<ITG<int>>());
Assert.IsType<TG<string>>(container2.Resolve<ITG<string>>());
}

[Theory]
[ClassData(typeof(CompilerTypeTestData))]
public void FactoryTests_Resolve_Action_Without_Implementation_Open_Generic(CompilerType compilerType)
{
using var container1 = new StashboxContainer().Register(typeof(ITG<>), typeof(TG<>));

using var container2 = new StashboxContainer(c => c.WithCompiler(compilerType))
.Register(typeof(ITG<>), c => c.WithFactory<TypeInformation>(t => container1.Resolve(t.Type)));

Assert.IsType<TG<int>>(container2.Resolve<ITG<int>>());
Assert.IsType<TG<string>>(container2.Resolve<ITG<string>>());
}

interface ITG<T> { }

Expand Down

0 comments on commit b6f64ef

Please sign in to comment.