Skip to content

Commit

Permalink
Fix nested registration scope copy which used to add more registratio…
Browse files Browse the repository at this point in the history
…n contexts than in the original scope thus giving more instances while resolving all components in a nested context
  • Loading branch information
ybainier committed Sep 21, 2021
1 parent 3e86a5a commit a08bc70
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 28 deletions.
4 changes: 2 additions & 2 deletions Hypodermic.Tests/Hypodermic.Tests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
Expand All @@ -48,7 +48,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
Expand Down
20 changes: 20 additions & 0 deletions Hypodermic.Tests/NestedContainerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,26 @@ namespace Testing
BOOST_CHECK(instanceAfterNestedContainerIsReleased == instance);
}

BOOST_AUTO_TEST_CASE(should_resolve_all_the_same_components)
{
// Arrange
ContainerBuilder builder;
builder.registerType< DefaultConstructible1 >().as< DefaultConstructibleBase >().asSelf();
builder.registerType< DefaultConstructible2 >().as< DefaultConstructibleBase >().asSelf();

auto container = builder.build();
auto components = container->resolveAll< DefaultConstructibleBase >();

// Act
ContainerBuilder nestedBuilder;
auto nestedContainer = nestedBuilder.buildNestedContainerFrom(*container);

auto componentsFromNestedContainer = nestedContainer->resolveAll< DefaultConstructibleBase >();

// Assert
BOOST_CHECK_EQUAL(components.size(), componentsFromNestedContainer.size());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace Testing
Expand Down
9 changes: 7 additions & 2 deletions Hypodermic/ContainerBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ namespace Hypodermic
{
if (registration->typeAliases().empty())
{
registeredTypeAliasKeys.insert(createKeyForType(registration->instanceType()));
addRegistration(createKeyForType(registration->instanceType()), nullptr);
return;
}

for (auto&& x : registration->typeAliases())
registeredTypeAliasKeys.insert(x.first);
addRegistration(x.first, nullptr);
}

void addRegistration(const TypeAliasKey& typeAliasKey, const std::shared_ptr< IRegistration >& /*registration*/) override
{
registeredTypeAliasKeys.insert(typeAliasKey);
}

std::unordered_set< TypeAliasKey > registeredTypeAliasKeys;
Expand Down
7 changes: 4 additions & 3 deletions Hypodermic/Hypodermic.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
Expand All @@ -46,7 +46,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<ConfigurationType>StaticLibrary</ConfigurationType>
Expand Down Expand Up @@ -165,6 +165,7 @@
<ClInclude Include="EnforceDependencyNotAlreadyRegistered.h" />
<ClInclude Include="FactoryWrapper.h" />
<ClInclude Include="Hypodermic.h" />
<ClInclude Include="InstanceFactoryDeducer.h" />
<ClInclude Include="IRegistrationRegistry.h" />
<ClInclude Include="IResolutionContext.h" />
<ClInclude Include="MetaContains.h" />
Expand Down
1 change: 1 addition & 0 deletions Hypodermic/Hypodermic.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -317,5 +317,6 @@
<ClInclude Include="EnforceDependencyNotAlreadyRegistered.h">
<Filter>Descriptors\Extensions</Filter>
</ClInclude>
<ClInclude Include="InstanceFactoryDeducer.h" />
</ItemGroup>
</Project>
5 changes: 3 additions & 2 deletions Hypodermic/IRegistrationRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

namespace Hypodermic
{

class IRegistration;

class IRegistration;


class IRegistrationRegistry
{
public:
virtual ~IRegistrationRegistry() = default;

virtual void addRegistration(const std::shared_ptr< IRegistration >& registration) = 0;
virtual void addRegistration(const TypeAliasKey& typeAliasKey, const std::shared_ptr< IRegistration >& registration) = 0;
};

} // namespace Hypodermic
1 change: 0 additions & 1 deletion Hypodermic/IRegistrationScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ namespace Hypodermic
virtual bool tryGetRegistrations(const TypeAliasKey& typeAliasKey, std::vector< std::shared_ptr< RegistrationContext > >& registrationContexts) const = 0;

virtual void copyTo(IRegistrationScope& other) const = 0;
virtual void addRegistrationContext(const std::shared_ptr< RegistrationContext >& registrationContext) = 0;
};

} // namespace Hypodermic
4 changes: 2 additions & 2 deletions Hypodermic/NestedRegistrationScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ namespace Hypodermic
scope().copyTo(other);
}

void addRegistrationContext(const std::shared_ptr< RegistrationContext >& registrationContext) override
void addRegistration(const TypeAliasKey& typeAliasKey, const std::shared_ptr< IRegistration >& registration) override
{
writeScope().addRegistrationContext(registrationContext);
writeScope().addRegistration(typeAliasKey, registration);
}

private:
Expand Down
23 changes: 7 additions & 16 deletions Hypodermic/RegistrationScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,12 @@ namespace Hypodermic
copyFallbackRegistrationContextsTo(other);
}

void addRegistrationContext(const std::shared_ptr< RegistrationContext >& registrationContext) override
{
if (registrationContext->registration()->typeAliases().empty())
{
addRegistrationContext(createKeyForType(registrationContext->registration()->instanceType()), registrationContext);
return;
}

for (auto&& x : registrationContext->registration()->typeAliases())
addRegistrationContext(x.first, registrationContext);
}

private:
void addRegistration(const TypeAliasKey& typeAliasKey, const std::shared_ptr< IRegistration >& registration)
void addRegistration(const TypeAliasKey& typeAliasKey, const std::shared_ptr< IRegistration >& registration) override
{
addRegistrationContext(typeAliasKey, std::make_shared< RegistrationContext >(m_resolutionContainer, registration));
}

private:
void addRegistrationContext(const TypeAliasKey& typeAliasKey, const std::shared_ptr< RegistrationContext >& registrationContext)
{
if (registrationContext->registration()->isFallback())
Expand Down Expand Up @@ -120,9 +108,12 @@ namespace Hypodermic
{
for (auto& x : contextsByBaseTypes)
{
for (auto& registrationContext : x.second)
auto& typeAliasKey = x.first;
auto& contexts = x.second;

for (auto& registrationContext : contexts)
{
other.addRegistrationContext(registrationContext);
other.addRegistration(typeAliasKey, registrationContext->registration());
}
}
}
Expand Down

0 comments on commit a08bc70

Please sign in to comment.