Skip to content

Commit

Permalink
Merge pull request #42 from JSkimming/container-on-context
Browse files Browse the repository at this point in the history
Add the container to the construction context
  • Loading branch information
JSkimming authored May 30, 2017
2 parents 093559b + e5c33d2 commit 9f8c9a7
Show file tree
Hide file tree
Showing 24 changed files with 209 additions and 49 deletions.
8 changes: 8 additions & 0 deletions src/Abioc/ConstructionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public struct ConstructionContext<TExtra>
/// </summary>
public readonly Type RecipientType;

/// <summary>
/// Gets the abioc <see cref="IContainer{TExtra}"/> used for this construction request.
/// </summary>
public readonly IContainer<TExtra> Container;

/// <summary>
/// Gets the <see cref="Extra"/> construction context information to be propitiated through all construction.
/// </summary>
Expand All @@ -54,11 +59,13 @@ public struct ConstructionContext<TExtra>
/// <param name="implementationType">The <see cref="ImplementationType"/>.</param>
/// <param name="serviceType">The <see cref="ServiceType"/>.</param>
/// <param name="recipientType">The <see cref="RecipientType"/>.</param>
/// <param name="container">The abioc <see cref="Container"/> used for this construction request.</param>
/// <param name="extra">The <see cref="Extra"/> construction context information.</param>
public ConstructionContext(
Type implementationType,
Type serviceType,
Type recipientType,
IContainer<TExtra> container = null,
TExtra extra = default(TExtra))
{
if (implementationType == null)
Expand All @@ -71,6 +78,7 @@ public ConstructionContext(
ImplementationType = implementationType;
ServiceType = serviceType;
RecipientType = recipientType;
Container = container;
Extra = extra;
}
}
Expand Down
15 changes: 14 additions & 1 deletion src/Abioc/ConstructionContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,26 @@ public static class ConstructionContextExtensions
/// The type of the <see cref="ConstructionContext{TExtra}.Extra"/> construction context information.
/// </typeparam>
/// <param name="context">The source <see cref="ConstructionContext{TExtra}"/>.</param>
/// <param name="container">
/// The abioc <see cref="IContainer{TExtra}"/> used for this construction request.
/// </param>
/// <param name="extra">
/// The <see cref="ConstructionContext{TExtra}.Extra"/> construction context information.
/// </param>
/// <returns>An updated <see cref="ConstructionContext{TExtra}"/>.</returns>
public static ConstructionContext<TExtra> Initialize<TExtra>(
this ConstructionContext<TExtra> context,
IContainer<TExtra> container,
TExtra extra)
{
if (container == null)
throw new ArgumentNullException(nameof(container));

return new ConstructionContext<TExtra>(
context.ImplementationType,
context.ServiceType,
context.RecipientType,
container,
extra);
}

Expand All @@ -55,7 +63,12 @@ public static ConstructionContext<TExtra> Update<TExtra>(
serviceType = serviceType ?? context.ServiceType;
recipientType = recipientType ?? context.RecipientType;

return new ConstructionContext<TExtra>(implementationType, serviceType, recipientType, context.Extra);
return new ConstructionContext<TExtra>(
implementationType,
serviceType,
recipientType,
context.Container,
context.Extra);
}
}
}
38 changes: 36 additions & 2 deletions src/Abioc/Generation/CodeGeneration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ private static string GenerateGetServiceMethod(GenerationContext context)
: string.Empty;

string contextVariable = context.HasConstructionContext
? $"{NewLine} var context = {context.ConstructionContext}.Default.Initialize(extraData);"
? $"{NewLine} var context = {context.ConstructionContext}.Default.Initialize(this, extraData);"
: string.Empty;

var builder = new StringBuilder(1024);
Expand Down Expand Up @@ -265,6 +265,23 @@ string GetCaseSnippet(Type key, IComposition composition)

builder.AppendFormat("{0} }}{0}{0} return null;{0}}}", NewLine);

// Add the genetic GetService method.
if (context.HasConstructionContext)
{
builder.AppendFormat(
"{0}{0}public TService GetService<TService>({0} {1} extraData){0}{{{0} " +
"return (TService)GetService(typeof(TService), extraData);{0}}}",
NewLine,
context.ExtraDataType);
}
else
{
builder.AppendFormat(
"{0}{0}public TService GetService<TService>(){0}{{{0} " +
"return (TService)GetService(typeof(TService));{0}}}",
NewLine);
}

return builder.ToString();
}

Expand All @@ -278,7 +295,7 @@ private static string GenerateGetServicesMethod(GenerationContext context)
: string.Empty;

string contextVariable = context.HasConstructionContext
? $"{NewLine} var context = {context.ConstructionContext}.Default.Initialize(extraData);"
? $"{NewLine} var context = {context.ConstructionContext}.Default.Initialize(this, extraData);"
: string.Empty;

var builder = new StringBuilder(1024);
Expand Down Expand Up @@ -323,6 +340,23 @@ from composition in compositions

builder.AppendFormat("{0} }}{0}}}", NewLine);

// Add the genetic GetServices method.
if (context.HasConstructionContext)
{
builder.AppendFormat(
"{0}{0}public System.Collections.Generic.IEnumerable<TService> GetServices<TService>({0} {1}" +
" extraData){0}{{{0} return GetServices(typeof(TService), extraData).Cast<TService>();{0}}}",
NewLine,
context.ExtraDataType);
}
else
{
builder.AppendFormat(
"{0}{0}public System.Collections.Generic.IEnumerable<TService> GetServices<TService>(){0}{{{0} " +
"return GetServices(typeof(TService)).Cast<TService>();{0}}}",
NewLine);
}

return builder.ToString();
}

Expand Down
18 changes: 17 additions & 1 deletion src/Abioc/IContainer.WithContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,27 @@ public interface IContainer<in TExtra>
object GetService(Type serviceType, TExtra extraData);

/// <summary>
/// Gets any services of the <paramref name="serviceType"/>.
/// Gets the service of type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The type of the service to get.</typeparam>
/// <param name="extraData">The custom extra data used during construction.</param>
/// <returns>The service of type <typeparamref name="TService"/>.</returns>
TService GetService<TService>(TExtra extraData);

/// <summary>
/// Gets any services of the type <paramref name="serviceType"/>.
/// </summary>
/// <param name="serviceType">The type of the services to get.</param>
/// <param name="extraData">The custom extra data used during construction.</param>
/// <returns>Any services of the <paramref name="serviceType"/>.</returns>
IEnumerable<object> GetServices(Type serviceType, TExtra extraData);

/// <summary>
/// Gets any services of the type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The type of the service to get.</typeparam>
/// <param name="extraData">The custom extra data used during construction.</param>
/// <returns>Any services of the type .</returns>
IEnumerable<TService> GetServices<TService>(TExtra extraData);
}
}
16 changes: 15 additions & 1 deletion src/Abioc/IContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,24 @@ public interface IContainer
object GetService(Type serviceType);

/// <summary>
/// Gets any services of the <paramref name="serviceType"/>.
/// Gets the service of type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The type of the service to get.</typeparam>
/// <returns>The service of type <typeparamref name="TService"/>.</returns>
TService GetService<TService>();

/// <summary>
/// Gets any services of the type <paramref name="serviceType"/>.
/// </summary>
/// <param name="serviceType">The type of the services to get.</param>
/// <returns>Any services of the <paramref name="serviceType"/>.</returns>
IEnumerable<object> GetServices(Type serviceType);

/// <summary>
/// Gets any services of the type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The type of the service to get.</typeparam>
/// <returns>Any services of the type <typeparamref name="TService"/>.</returns>
IEnumerable<TService> GetServices<TService>();
}
}
7 changes: 7 additions & 0 deletions test/Abioc.Tests/Abioc.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=4.19.2.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions.Core, Version=4.19.2.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Moq, Version=4.7.10.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\..\packages\Moq.4.7.10\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
Expand Down Expand Up @@ -81,6 +87,7 @@
<Compile Include="CreateObjectGraphTests.cs" />
<Compile Include="EnumerableDependencyTests.cs" />
<Compile Include="ExampleServices.cs" />
<Compile Include="FactoriesUsingTheContainerTests.cs" />
<Compile Include="FactoryServicesTests.cs" />
<Compile Include="GenerationContextExtensionsTests.cs" />
<Compile Include="InjectedSingletonTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions test/Abioc.Tests/Abioc.TestsCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="4.19.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="Moq" Version="4.7.10" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.analyzers" Version="0.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
Expand Down
8 changes: 4 additions & 4 deletions test/Abioc.Tests/AbstractDependencies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public void ItShouldCreateAClassWithMixedDependencies()

public class WhenRegisteringAbstractDependenciesWithAContext : WhenRegisteringAbstractDependenciesBase
{
private readonly AbiocContainer<int> _container;
private readonly IContainer<int> _container;

public WhenRegisteringAbstractDependenciesWithAContext(ITestOutputHelper output)
{
Expand All @@ -170,7 +170,7 @@ public WhenRegisteringAbstractDependenciesWithAContext(ITestOutputHelper output)

public class WhenRegisteringAbstractDependenciesWithoutAContext : WhenRegisteringAbstractDependenciesBase
{
private readonly AbiocContainer _container;
private readonly IContainer _container;

public WhenRegisteringAbstractDependenciesWithoutAContext(ITestOutputHelper output)
{
Expand Down Expand Up @@ -255,7 +255,7 @@ public void ItShouldCreateAClassWithMixedDependencies()
public class WhenRegisteringAClassThatImplementsMultipleAbstractionsWithAContext
: WhenRegisteringAClassThatImplementsMultipleAbstractionsBase
{
private readonly AbiocContainer<int> _container;
private readonly IContainer<int> _container;

public WhenRegisteringAClassThatImplementsMultipleAbstractionsWithAContext(ITestOutputHelper output)
{
Expand All @@ -279,7 +279,7 @@ public WhenRegisteringAClassThatImplementsMultipleAbstractionsWithAContext(ITest
public class WhenRegisteringAClassThatImplementsMultipleAbstractionsWithoutAContext
: WhenRegisteringAClassThatImplementsMultipleAbstractionsBase
{
private readonly AbiocContainer _container;
private readonly IContainer _container;

public WhenRegisteringAClassThatImplementsMultipleAbstractionsWithoutAContext(ITestOutputHelper output)
{
Expand Down
8 changes: 4 additions & 4 deletions test/Abioc.Tests/CommonInterfaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void ItShouldThrowADiExceptionIfGettingAsASingleService()
public class WhenRegisteringTwoClassThatImplementTheSameInterfaceWithAContext
: WhenRegisteringTwoClassThatImplementTheSameInterfaceBase
{
private readonly AbiocContainer<int> _container;
private readonly IContainer<int> _container;

public WhenRegisteringTwoClassThatImplementTheSameInterfaceWithAContext(ITestOutputHelper output)
{
Expand All @@ -72,7 +72,7 @@ public WhenRegisteringTwoClassThatImplementTheSameInterfaceWithAContext(ITestOut
public class WhenRegisteringTwoClassThatImplementTheSameInterfaceWithoutAContext
: WhenRegisteringTwoClassThatImplementTheSameInterfaceBase
{
private readonly AbiocContainer _container;
private readonly IContainer _container;

public WhenRegisteringTwoClassThatImplementTheSameInterfaceWithoutAContext(ITestOutputHelper output)
{
Expand Down Expand Up @@ -133,7 +133,7 @@ public void ItShouldThrowADiExceptionIfGettingAsASingleService()
public class WhenFactoringTwoClassThatImplementTheSameInterfaceWithAContext
: WhenFactoringTwoClassThatImplementTheSameInterfaceBase
{
private readonly AbiocContainer<int> _container;
private readonly IContainer<int> _container;

public WhenFactoringTwoClassThatImplementTheSameInterfaceWithAContext(ITestOutputHelper output)
{
Expand All @@ -157,7 +157,7 @@ public WhenFactoringTwoClassThatImplementTheSameInterfaceWithAContext(ITestOutpu
public class WhenFactoringTwoClassThatImplementTheSameInterfaceWithoutAContext
: WhenFactoringTwoClassThatImplementTheSameInterfaceBase
{
private readonly AbiocContainer _container;
private readonly IContainer _container;

public WhenFactoringTwoClassThatImplementTheSameInterfaceWithoutAContext(ITestOutputHelper output)
{
Expand Down
7 changes: 6 additions & 1 deletion test/Abioc.Tests/ConstructionContextExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Abioc
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Moq;
using Xunit;

public class WhenUpdatingAConstructionContext
Expand All @@ -16,7 +17,8 @@ public class WhenUpdatingAConstructionContext
public WhenUpdatingAConstructionContext()
{
string extra = Guid.NewGuid().ToString("D").ToUpperInvariant();
_initialValue = ConstructionContext<string>.Default.Initialize(extra);
IContainer<string> container = new Mock<IContainer<string>>().Object;
_initialValue = ConstructionContext<string>.Default.Initialize(container, extra);
}

[Fact]
Expand All @@ -29,6 +31,7 @@ public void ItShouldUpdateImplementationTypeIfSpecified()
context.ImplementationType.Should().Be(GetType());
context.ServiceType.Should().Be(typeof(void));
context.RecipientType.Should().Be(typeof(void));
context.Container.Should().Be(_initialValue.Container);
context.Extra.Should().Be(_initialValue.Extra);
}

Expand All @@ -42,6 +45,7 @@ public void ItShouldUpdateServiceTypeIfSpecified()
context.ImplementationType.Should().Be(typeof(void));
context.ServiceType.Should().Be(GetType());
context.RecipientType.Should().Be(typeof(void));
context.Container.Should().Be(_initialValue.Container);
context.Extra.Should().Be(_initialValue.Extra);
}

Expand All @@ -55,6 +59,7 @@ public void ItShouldUpdateRecipientTypeIfSpecified()
context.ImplementationType.Should().Be(typeof(void));
context.ServiceType.Should().Be(typeof(void));
context.RecipientType.Should().Be(GetType());
context.Container.Should().Be(_initialValue.Container);
context.Extra.Should().Be(_initialValue.Extra);
}
}
Expand Down
6 changes: 3 additions & 3 deletions test/Abioc.Tests/ConstructionContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class PropertyDependentClass

public abstract class FactoringClassWithAContextBase
{
protected AbiocContainer<Guid> Container;
protected IContainer<Guid> Container;

[Fact]
public void ItShouldSpecifyTheImplementationTypeAsTheConcreteClassIfRequestingTheConcreteClass()
Expand Down Expand Up @@ -163,7 +163,7 @@ public WhenFactoringAWeaklyTypedClassWithAContext(ITestOutputHelper output)

public abstract class FactoringClassWithAContextAsAConstructorDependencyBase
{
protected AbiocContainer<Guid> Container;
protected IContainer<Guid> Container;

[Fact]
public void ItShouldSpecifyRecipientTypeAsTheDependentClassForTheConcreteDependency()
Expand Down Expand Up @@ -239,7 +239,7 @@ public WhenFactoringAWeaklyTypedClassWithAContextAsAConstructorDependency(ITestO

public abstract class FactoringClassWithAContextAsAPropertyDependencyBase
{
protected AbiocContainer<Guid> Container;
protected IContainer<Guid> Container;

[Fact]
public void ItShouldSpecifyRecipientTypeAsTheDependentClassForTheConcreteDependency()
Expand Down
Loading

0 comments on commit 9f8c9a7

Please sign in to comment.