From 4410206ec4a74edad7c7737647c7a795d4dbe978 Mon Sep 17 00:00:00 2001 From: Mike Bierlee Date: Mon, 1 Jan 2018 15:54:32 +0100 Subject: [PATCH] Update copyrigths And convert tabs to spaces --- .gitignore | 1 + LICENSE.txt | 2 +- README.md | 2 +- docs/poodinis.html | 2 +- docs/poodinis/autowire.html | 2 +- docs/poodinis/autowire/AssignNewInstance.html | 2 +- .../poodinis/autowire/OptionalDependency.html | 2 +- docs/poodinis/autowire/autowire.html | 2 +- docs/poodinis/autowire/globalAutowire.html | 2 +- docs/poodinis/container.html | 2 +- ...ndencyContainer.clearAllRegistrations.html | 2 +- .../container/DependencyContainer.html | 2 +- .../DependencyContainer.register.html | 2 +- ...ependencyContainer.removeRegistration.html | 2 +- .../DependencyContainer.resolve.html | 2 +- .../DependencyContainer.resolveAll.html | 2 +- ...iner.setPersistentRegistrationOptions.html | 2 +- ...Container.setPersistentResolveOptions.html | 2 +- ...er.unsetPersistentRegistrationOptions.html | 2 +- ...ntainer.unsetPersistentResolveOptions.html | 2 +- docs/poodinis/container/PostConstruct.html | 2 +- docs/poodinis/container/PreDestroy.html | 2 +- .../container/RegistrationException.html | 2 +- .../container/RegistrationOption.html | 2 +- docs/poodinis/container/ResolveException.html | 2 +- docs/poodinis/container/ResolveOption.html | 2 +- docs/poodinis/context.html | 2 +- docs/poodinis/context/Component.html | 2 +- docs/poodinis/context/Prototype.html | 2 +- docs/poodinis/context/RegisterByType.html | 2 +- docs/poodinis/context/registerContext.html | 2 +- docs/poodinis/factory.html | 2 +- docs/poodinis/polyfill.html | 2 +- docs/poodinis/registration.html | 2 +- .../registration/existingInstance.html | 2 +- docs/poodinis/registration/newInstance.html | 2 +- .../poodinis/registration/singleInstance.html | 2 +- docs/poodinis/valueinjection.html | 2 +- .../valueinjection/MandatoryValue.html | 2 +- .../valueinjection/MandatoryValue.key.html | 2 +- docs/poodinis/valueinjection/Value.html | 2 +- docs/poodinis/valueinjection/Value.key.html | 2 +- .../ValueInjectionException.html | 2 +- .../valueinjection/ValueInjector.get.html | 2 +- .../valueinjection/ValueInjector.html | 2 +- .../ValueNotAvailableException.html | 2 +- dub.json | 2 +- example/annotations/app.d | 2 +- example/applicationcontext/app.d | 2 +- example/arraycompletion/app.d | 2 +- example/constructorinjection/app.d | 2 +- example/postconstructorpredestructor/app.d | 2 +- example/qualifiers/app.d | 2 +- example/quickstart/app.d | 2 +- example/registeronresolve/app.d | 2 +- example/valueinjection/app.d | 2 +- source/poodinis/autowire.d | 248 ++-- source/poodinis/container.d | 680 ++++----- source/poodinis/context.d | 52 +- source/poodinis/factory.d | 224 +-- source/poodinis/imports.d | 29 +- source/poodinis/package.d | 2 +- source/poodinis/polyfill.d | 56 +- source/poodinis/registration.d | 116 +- source/poodinis/valueinjection.d | 58 +- test/poodinis/autowiretest.d | 268 ++-- test/poodinis/containertest.d | 1064 +++++++-------- test/poodinis/contexttest.d | 168 +-- test/poodinis/factorytest.d | 208 +-- test/poodinis/foreigndependencies.d | 4 +- test/poodinis/registrationtest.d | 82 +- test/poodinis/testclasses.d | 1210 ++++++++--------- test/poodinis/testmain.d | 2 +- test/poodinis/valueinjectiontest.d | 198 +-- 74 files changed, 2396 insertions(+), 2384 deletions(-) diff --git a/.gitignore b/.gitignore index 45c7282..a667126 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ /.idea /*.iml /out +/classes \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt index a55b4c3..11d23ed 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2014-2017 Mike Bierlee +Copyright (c) 2014-2018 Mike Bierlee Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index d59700d..6e5a83e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Poodinis Dependency Injection Framework ======================================= Version 8.0.1 -Copyright 2014-2017 Mike Bierlee +Copyright 2014-2018 Mike Bierlee Licensed under the terms of the MIT license - See [LICENSE.txt](LICENSE.txt) Master: [![Build Status](https://api.travis-ci.org/mbierlee/poodinis.png?branch=master)](https://travis-ci.org/mbierlee/poodinis) - Dev: [![Build Status](https://api.travis-ci.org/mbierlee/poodinis.png?branch=develop)](https://travis-ci.org/mbierlee/poodinis) diff --git a/docs/poodinis.html b/docs/poodinis.html index a0edfb5..86c5fe8 100644 --- a/docs/poodinis.html +++ b/docs/poodinis.html @@ -83,7 +83,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/autowire.html b/docs/poodinis/autowire.html index 4cb6799..6f78768 100644 --- a/docs/poodinis/autowire.html +++ b/docs/poodinis/autowire.html @@ -155,7 +155,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/autowire/AssignNewInstance.html b/docs/poodinis/autowire/AssignNewInstance.html index 1b12ef5..1e9c476 100644 --- a/docs/poodinis/autowire/AssignNewInstance.html +++ b/docs/poodinis/autowire/AssignNewInstance.html @@ -101,7 +101,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/autowire/OptionalDependency.html b/docs/poodinis/autowire/OptionalDependency.html index ba8ea94..27d5834 100644 --- a/docs/poodinis/autowire/OptionalDependency.html +++ b/docs/poodinis/autowire/OptionalDependency.html @@ -93,7 +93,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/autowire/autowire.html b/docs/poodinis/autowire/autowire.html index b70aca3..2520cb9 100644 --- a/docs/poodinis/autowire/autowire.html +++ b/docs/poodinis/autowire/autowire.html @@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/autowire/globalAutowire.html b/docs/poodinis/autowire/globalAutowire.html index 5f67b14..87d832a 100644 --- a/docs/poodinis/autowire/globalAutowire.html +++ b/docs/poodinis/autowire/globalAutowire.html @@ -104,7 +104,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container.html b/docs/poodinis/container.html index 8f405f7..b6d7b98 100644 --- a/docs/poodinis/container.html +++ b/docs/poodinis/container.html @@ -177,7 +177,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.clearAllRegistrations.html b/docs/poodinis/container/DependencyContainer.clearAllRegistrations.html index c0b772c..4b8d9c6 100644 --- a/docs/poodinis/container/DependencyContainer.clearAllRegistrations.html +++ b/docs/poodinis/container/DependencyContainer.clearAllRegistrations.html @@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.html b/docs/poodinis/container/DependencyContainer.html index 8ba76d7..53be72c 100644 --- a/docs/poodinis/container/DependencyContainer.html +++ b/docs/poodinis/container/DependencyContainer.html @@ -207,7 +207,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.register.html b/docs/poodinis/container/DependencyContainer.register.html index c5b8fcf..939a607 100644 --- a/docs/poodinis/container/DependencyContainer.register.html +++ b/docs/poodinis/container/DependencyContainer.register.html @@ -162,7 +162,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.removeRegistration.html b/docs/poodinis/container/DependencyContainer.removeRegistration.html index bdfb7bb..dc92b7c 100644 --- a/docs/poodinis/container/DependencyContainer.removeRegistration.html +++ b/docs/poodinis/container/DependencyContainer.removeRegistration.html @@ -97,7 +97,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.resolve.html b/docs/poodinis/container/DependencyContainer.resolve.html index 0e84993..741b42a 100644 --- a/docs/poodinis/container/DependencyContainer.resolve.html +++ b/docs/poodinis/container/DependencyContainer.resolve.html @@ -189,7 +189,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.resolveAll.html b/docs/poodinis/container/DependencyContainer.resolveAll.html index 874f62c..35e7a35 100644 --- a/docs/poodinis/container/DependencyContainer.resolveAll.html +++ b/docs/poodinis/container/DependencyContainer.resolveAll.html @@ -109,7 +109,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.setPersistentRegistrationOptions.html b/docs/poodinis/container/DependencyContainer.setPersistentRegistrationOptions.html index 86249b8..e206ab7 100644 --- a/docs/poodinis/container/DependencyContainer.setPersistentRegistrationOptions.html +++ b/docs/poodinis/container/DependencyContainer.setPersistentRegistrationOptions.html @@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.setPersistentResolveOptions.html b/docs/poodinis/container/DependencyContainer.setPersistentResolveOptions.html index 70ab8a0..5c8b0a7 100644 --- a/docs/poodinis/container/DependencyContainer.setPersistentResolveOptions.html +++ b/docs/poodinis/container/DependencyContainer.setPersistentResolveOptions.html @@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.unsetPersistentRegistrationOptions.html b/docs/poodinis/container/DependencyContainer.unsetPersistentRegistrationOptions.html index 083e42f..3a9c974 100644 --- a/docs/poodinis/container/DependencyContainer.unsetPersistentRegistrationOptions.html +++ b/docs/poodinis/container/DependencyContainer.unsetPersistentRegistrationOptions.html @@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/DependencyContainer.unsetPersistentResolveOptions.html b/docs/poodinis/container/DependencyContainer.unsetPersistentResolveOptions.html index 41d83ee..4232560 100644 --- a/docs/poodinis/container/DependencyContainer.unsetPersistentResolveOptions.html +++ b/docs/poodinis/container/DependencyContainer.unsetPersistentResolveOptions.html @@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/PostConstruct.html b/docs/poodinis/container/PostConstruct.html index 26934ac..f7aa560 100644 --- a/docs/poodinis/container/PostConstruct.html +++ b/docs/poodinis/container/PostConstruct.html @@ -96,7 +96,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/PreDestroy.html b/docs/poodinis/container/PreDestroy.html index b874768..5ca43c2 100644 --- a/docs/poodinis/container/PreDestroy.html +++ b/docs/poodinis/container/PreDestroy.html @@ -96,7 +96,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/RegistrationException.html b/docs/poodinis/container/RegistrationException.html index fe3a752..bce7d12 100644 --- a/docs/poodinis/container/RegistrationException.html +++ b/docs/poodinis/container/RegistrationException.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/RegistrationOption.html b/docs/poodinis/container/RegistrationOption.html index 2697f44..3bcf46e 100644 --- a/docs/poodinis/container/RegistrationOption.html +++ b/docs/poodinis/container/RegistrationOption.html @@ -107,7 +107,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/ResolveException.html b/docs/poodinis/container/ResolveException.html index 15830bf..522e4bb 100644 --- a/docs/poodinis/container/ResolveException.html +++ b/docs/poodinis/container/ResolveException.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/container/ResolveOption.html b/docs/poodinis/container/ResolveOption.html index 788fb34..aef18b9 100644 --- a/docs/poodinis/container/ResolveOption.html +++ b/docs/poodinis/container/ResolveOption.html @@ -116,7 +116,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/context.html b/docs/poodinis/context.html index 46ede30..854953f 100644 --- a/docs/poodinis/context.html +++ b/docs/poodinis/context.html @@ -142,7 +142,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/context/Component.html b/docs/poodinis/context/Component.html index 5250ed7..4e02eb4 100644 --- a/docs/poodinis/context/Component.html +++ b/docs/poodinis/context/Component.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/context/Prototype.html b/docs/poodinis/context/Prototype.html index a699043..269ab9a 100644 --- a/docs/poodinis/context/Prototype.html +++ b/docs/poodinis/context/Prototype.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/context/RegisterByType.html b/docs/poodinis/context/RegisterByType.html index 5bea0a7..16a3078 100644 --- a/docs/poodinis/context/RegisterByType.html +++ b/docs/poodinis/context/RegisterByType.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/context/registerContext.html b/docs/poodinis/context/registerContext.html index 6021bdc..27c14fa 100644 --- a/docs/poodinis/context/registerContext.html +++ b/docs/poodinis/context/registerContext.html @@ -100,7 +100,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/factory.html b/docs/poodinis/factory.html index 1da85e9..9833dea 100644 --- a/docs/poodinis/factory.html +++ b/docs/poodinis/factory.html @@ -83,7 +83,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/polyfill.html b/docs/poodinis/polyfill.html index 266a8ec..1a41795 100644 --- a/docs/poodinis/polyfill.html +++ b/docs/poodinis/polyfill.html @@ -102,7 +102,7 @@ document.getElementById('symbolSearchPane').style.display = 'block'; Mike Bierlee (m.bierlee@lostmoment.com)

-

Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2017 Mike Bierlee +

Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2018 Mike Bierlee

boost.org/LICENSE_1_0.txt, Boost License 1.0 diff --git a/docs/poodinis/registration.html b/docs/poodinis/registration.html index 9bc8214..24bab4b 100644 --- a/docs/poodinis/registration.html +++ b/docs/poodinis/registration.html @@ -121,7 +121,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/registration/existingInstance.html b/docs/poodinis/registration/existingInstance.html index 0283faf..ef17730 100644 --- a/docs/poodinis/registration/existingInstance.html +++ b/docs/poodinis/registration/existingInstance.html @@ -97,7 +97,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/registration/newInstance.html b/docs/poodinis/registration/newInstance.html index a064655..90930bf 100644 --- a/docs/poodinis/registration/newInstance.html +++ b/docs/poodinis/registration/newInstance.html @@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/registration/singleInstance.html b/docs/poodinis/registration/singleInstance.html index 783f162..7b5b170 100644 --- a/docs/poodinis/registration/singleInstance.html +++ b/docs/poodinis/registration/singleInstance.html @@ -98,7 +98,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection.html b/docs/poodinis/valueinjection.html index f97318b..a3de325 100644 --- a/docs/poodinis/valueinjection.html +++ b/docs/poodinis/valueinjection.html @@ -156,7 +156,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/MandatoryValue.html b/docs/poodinis/valueinjection/MandatoryValue.html index ebacc2e..d6868be 100644 --- a/docs/poodinis/valueinjection/MandatoryValue.html +++ b/docs/poodinis/valueinjection/MandatoryValue.html @@ -120,7 +120,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/MandatoryValue.key.html b/docs/poodinis/valueinjection/MandatoryValue.key.html index 87c1ee3..9fb7c97 100644 --- a/docs/poodinis/valueinjection/MandatoryValue.key.html +++ b/docs/poodinis/valueinjection/MandatoryValue.key.html @@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/Value.html b/docs/poodinis/valueinjection/Value.html index 342d3df..dbed213 100644 --- a/docs/poodinis/valueinjection/Value.html +++ b/docs/poodinis/valueinjection/Value.html @@ -120,7 +120,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/Value.key.html b/docs/poodinis/valueinjection/Value.key.html index 59da0ce..fc64aeb 100644 --- a/docs/poodinis/valueinjection/Value.key.html +++ b/docs/poodinis/valueinjection/Value.key.html @@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/ValueInjectionException.html b/docs/poodinis/valueinjection/ValueInjectionException.html index 5a7d9af..ebe714e 100644 --- a/docs/poodinis/valueinjection/ValueInjectionException.html +++ b/docs/poodinis/valueinjection/ValueInjectionException.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/ValueInjector.get.html b/docs/poodinis/valueinjection/ValueInjector.get.html index dba5865..fc424e1 100644 --- a/docs/poodinis/valueinjection/ValueInjector.get.html +++ b/docs/poodinis/valueinjection/ValueInjector.get.html @@ -103,7 +103,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/ValueInjector.html b/docs/poodinis/valueinjection/ValueInjector.html index cecd4f5..6aff98e 100644 --- a/docs/poodinis/valueinjection/ValueInjector.html +++ b/docs/poodinis/valueinjection/ValueInjector.html @@ -128,7 +128,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/docs/poodinis/valueinjection/ValueNotAvailableException.html b/docs/poodinis/valueinjection/ValueNotAvailableException.html index 3790d78..07c4163 100644 --- a/docs/poodinis/valueinjection/ValueNotAvailableException.html +++ b/docs/poodinis/valueinjection/ValueNotAvailableException.html @@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';

Mike Bierlee, m.bierlee@lostmoment.com

-

2014-2017 Mike Bierlee +

2014-2018 Mike Bierlee

This software is licensed under the terms of the MIT license. diff --git a/dub.json b/dub.json index 86a23b9..f5f19ab 100644 --- a/dub.json +++ b/dub.json @@ -3,7 +3,7 @@ "description" : "A dependency injection framework with support for autowiring.", "homepage": "http://lostmoment.com/open-source/poodinis", "authors": ["Mike Bierlee"], - "copyright": "Copyright 2014-2017 Mike Bierlee", + "copyright": "Copyright 2014-2018 Mike Bierlee", "license": "MIT", "-ddoxTool": "scod", "configurations": [ diff --git a/example/annotations/app.d b/example/annotations/app.d index ae9e70f..fcc6dd2 100644 --- a/example/annotations/app.d +++ b/example/annotations/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/applicationcontext/app.d b/example/applicationcontext/app.d index 0fff63d..bf64ea2 100644 --- a/example/applicationcontext/app.d +++ b/example/applicationcontext/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/arraycompletion/app.d b/example/arraycompletion/app.d index 47608a0..59b6c8d 100644 --- a/example/arraycompletion/app.d +++ b/example/arraycompletion/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/constructorinjection/app.d b/example/constructorinjection/app.d index 7327422..87a59af 100644 --- a/example/constructorinjection/app.d +++ b/example/constructorinjection/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/postconstructorpredestructor/app.d b/example/postconstructorpredestructor/app.d index 4ca7bbe..5c8147e 100644 --- a/example/postconstructorpredestructor/app.d +++ b/example/postconstructorpredestructor/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/qualifiers/app.d b/example/qualifiers/app.d index 3d19543..fa056c3 100644 --- a/example/qualifiers/app.d +++ b/example/qualifiers/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/quickstart/app.d b/example/quickstart/app.d index c5a20e3..4763fac 100644 --- a/example/quickstart/app.d +++ b/example/quickstart/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/registeronresolve/app.d b/example/registeronresolve/app.d index f095381..46728b4 100644 --- a/example/registeronresolve/app.d +++ b/example/registeronresolve/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/example/valueinjection/app.d b/example/valueinjection/app.d index f45ab24..ce8b90a 100644 --- a/example/valueinjection/app.d +++ b/example/valueinjection/app.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/source/poodinis/autowire.d b/source/poodinis/autowire.d index e95e790..d10c040 100644 --- a/source/poodinis/autowire.d +++ b/source/poodinis/autowire.d @@ -9,7 +9,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -30,7 +30,7 @@ import std.string; import std.traits; import std.range; -private struct UseMemberType {}; +private struct UseMemberType {} /** * UDA for annotating class members as candidates for autowiring. @@ -66,15 +66,15 @@ private struct UseMemberType {}; * will also be autowired because the autowire mechanism knows that member "fuelEngine" is an instance of "FuelEngine" */ struct Autowire(QualifierType) { - QualifierType qualifier; -}; + QualifierType qualifier; +} /** * UDA for marking autowired dependencies optional. * Optional dependencies will not lead to a resolveException when there is no type registered for them. * The member will remain null. */ -struct OptionalDependency {}; +struct OptionalDependency {} /** * UDA for annotating class members to be autowired with a new instance regardless of their registration scope. @@ -92,7 +92,7 @@ struct OptionalDependency {}; struct AssignNewInstance {} private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) { - writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress)); + writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress)); } /** @@ -105,129 +105,129 @@ private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAd * See_Also: Autowire */ public void autowire(Type)(shared(DependencyContainer) container, Type instance) { - debug(poodinisVerbose) { - printDebugAutowiredInstance(typeid(Type), &instance); - } + debug(poodinisVerbose) { + printDebugAutowiredInstance(typeid(Type), &instance); + } - // Recurse into base class if there are more between Type and Object in the hierarchy - static if(BaseClassesTuple!Type.length > 1) - { - autowire!(BaseClassesTuple!Type[0])(container, instance); - } + // Recurse into base class if there are more between Type and Object in the hierarchy + static if(BaseClassesTuple!Type.length > 1) + { + autowire!(BaseClassesTuple!Type[0])(container, instance); + } - foreach(index, name; FieldNameTuple!Type) { - autowireMember!(name, index, Type)(container, instance); - } + foreach(index, name; FieldNameTuple!Type) { + autowireMember!(name, index, Type)(container, instance); + } } private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType, void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) { - writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, candidateInstanceAddress, instanceType, instanceAddress, member)); + writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, candidateInstanceAddress, instanceType, instanceAddress, member)); } private void printDebugAutowiringArray(TypeInfo superTypeInfo, TypeInfo instanceType, void* instanceAddress, string member) { - writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", superTypeInfo, instanceType, instanceAddress, member)); + writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", superTypeInfo, instanceType, instanceAddress, member)); } private void autowireMember(string member, size_t memberIndex, Type)(shared(DependencyContainer) container, Type instance) { - foreach(attribute; __traits(getAttributes, Type.tupleof[memberIndex])) { - static if (is(attribute == Autowire!T, T)) { - injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance); - } else static if (__traits(isSame, attribute, Autowire)) { - injectInstance!(member, memberIndex, UseMemberType)(container, instance); - } else static if (is(typeof(attribute) == Value)) { - enum key = attribute.key; - injectValue!(member, memberIndex, key, false)(container, instance); - } else static if (is(typeof(attribute) == MandatoryValue)) { - enum key = attribute.key; - injectValue!(member, memberIndex, key, true)(container, instance); - } - } + foreach(attribute; __traits(getAttributes, Type.tupleof[memberIndex])) { + static if (is(attribute == Autowire!T, T)) { + injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance); + } else static if (__traits(isSame, attribute, Autowire)) { + injectInstance!(member, memberIndex, UseMemberType)(container, instance); + } else static if (is(typeof(attribute) == Value)) { + enum key = attribute.key; + injectValue!(member, memberIndex, key, false)(container, instance); + } else static if (is(typeof(attribute) == MandatoryValue)) { + enum key = attribute.key; + injectValue!(member, memberIndex, key, true)(container, instance); + } + } } private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(shared(DependencyContainer) container, Type instance) { - if (instance.tupleof[memberIndex] is null) { - alias MemberType = typeof(Type.tupleof[memberIndex]); - enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency); + if (instance.tupleof[memberIndex] is null) { + alias MemberType = typeof(Type.tupleof[memberIndex]); + enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency); - static if (isDynamicArray!MemberType) { - injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, instance); - } else { - injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container, instance); - } - } + static if (isDynamicArray!MemberType) { + injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, instance); + } else { + injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container, instance); + } + } } private void injectMultipleInstances(string member, size_t memberIndex, bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance) { - alias MemberElementType = ElementType!MemberType; - static if (isOptional) { - auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException); - } else { - auto instances = container.resolveAll!MemberElementType; - } + alias MemberElementType = ElementType!MemberType; + static if (isOptional) { + auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException); + } else { + auto instances = container.resolveAll!MemberElementType; + } - instance.tupleof[memberIndex] = instances; - debug(poodinisVerbose) { - printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member); - } + instance.tupleof[memberIndex] = instances; + debug(poodinisVerbose) { + printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member); + } } private void injectSingleInstance(string member, size_t memberIndex, bool isOptional, MemberType, QualifierType, Type)(shared(DependencyContainer) container, Type instance) { - debug(poodinisVerbose) { - TypeInfo qualifiedInstanceType = typeid(MemberType); - } + debug(poodinisVerbose) { + TypeInfo qualifiedInstanceType = typeid(MemberType); + } - enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance); + enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance); - MemberType qualifiedInstance; - static if (!is(QualifierType == UseMemberType)) { - qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance, isOptional)(container); - debug(poodinisVerbose) { - qualifiedInstanceType = typeid(QualifierType); - } - } else { - qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance, isOptional)(container); - } + MemberType qualifiedInstance; + static if (!is(QualifierType == UseMemberType)) { + qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance, isOptional)(container); + debug(poodinisVerbose) { + qualifiedInstanceType = typeid(QualifierType); + } + } else { + qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance, isOptional)(container); + } - instance.tupleof[memberIndex] = qualifiedInstance; + instance.tupleof[memberIndex] = qualifiedInstance; - debug(poodinisVerbose) { - printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member); - } + debug(poodinisVerbose) { + printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member); + } } private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew, bool isOptional)(shared(DependencyContainer) container) { - static if (createNew) { - auto instanceFactory = new InstanceFactory(); - instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), CreatesSingleton.no); - return cast(MemberType) instanceFactory.getInstance(); - } else { - static if (isOptional) { - return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException); - } else { - return container.resolve!(MemberType, QualifierType); - } - } + static if (createNew) { + auto instanceFactory = new InstanceFactory(); + instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), CreatesSingleton.no); + return cast(MemberType) instanceFactory.getInstance(); + } else { + static if (isOptional) { + return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException); + } else { + return container.resolve!(MemberType, QualifierType); + } + } } private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(shared(DependencyContainer) container, Type instance) { - alias MemberType = typeof(Type.tupleof[memberIndex]); - try { - auto injector = container.resolve!(ValueInjector!MemberType); - instance.tupleof[memberIndex] = injector.get(key); - debug(poodinisVerbose) { - printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key); - } - } catch (ResolveException e) { - throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s: value injector is missing for this type.", typeid(MemberType), typeid(Type), member)); - } catch (ValueNotAvailableException e) { - static if (mandatory) { - throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s", typeid(MemberType), typeid(Type), member), e); - } - } + alias MemberType = typeof(Type.tupleof[memberIndex]); + try { + auto injector = container.resolve!(ValueInjector!MemberType); + instance.tupleof[memberIndex] = injector.get(key); + debug(poodinisVerbose) { + printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key); + } + } catch (ResolveException e) { + throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s: value injector is missing for this type.", typeid(MemberType), typeid(Type), member)); + } catch (ValueNotAvailableException e) { + static if (mandatory) { + throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s", typeid(MemberType), typeid(Type), member), e); + } + } } private void printDebugValueInjection(TypeInfo instanceType, void* instanceAddress, string member, TypeInfo valueType, string key) { - writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s", key, valueType, instanceType, instanceAddress, member)); + writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s", key, valueType, instanceType, instanceAddress, member)); } /** @@ -237,48 +237,48 @@ private void printDebugValueInjection(TypeInfo instanceType, void* instanceAddre * Deprecated: Using the global container is undesired. See DependencyContainer.getInstance(). */ public deprecated void globalAutowire(Type)(Type instance) { - DependencyContainer.getInstance().autowire(instance); + DependencyContainer.getInstance().autowire(instance); } class AutowiredRegistration(RegistrationType : Object) : Registration { - private shared(DependencyContainer) container; + private shared(DependencyContainer) container; - public this(TypeInfo registeredType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { - super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer); - } + public this(TypeInfo registeredType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { + super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer); + } - public override Object getInstance(InstantiationContext context = new AutowireInstantiationContext()) { - enforce(!(originatingContainer is null), "The registration's originating container is null. There is no way to resolve autowire dependencies."); + public override Object getInstance(InstantiationContext context = new AutowireInstantiationContext()) { + enforce(!(originatingContainer is null), "The registration's originating container is null. There is no way to resolve autowire dependencies."); - RegistrationType instance = cast(RegistrationType) super.getInstance(context); + RegistrationType instance = cast(RegistrationType) super.getInstance(context); - AutowireInstantiationContext autowireContext = cast(AutowireInstantiationContext) context; - enforce(!(autowireContext is null), "Given instantiation context type could not be cast to an AutowireInstantiationContext. If you relied on using the default assigned context: make sure you're calling getInstance() on an instance of type AutowiredRegistration!"); - if (autowireContext.autowireInstance) { - originatingContainer.autowire(instance); - } + AutowireInstantiationContext autowireContext = cast(AutowireInstantiationContext) context; + enforce(!(autowireContext is null), "Given instantiation context type could not be cast to an AutowireInstantiationContext. If you relied on using the default assigned context: make sure you're calling getInstance() on an instance of type AutowiredRegistration!"); + if (autowireContext.autowireInstance) { + originatingContainer.autowire(instance); + } - this.preDestructor = getPreDestructor(instance); + this.preDestructor = getPreDestructor(instance); - return instance; - } + return instance; + } - private void delegate() getPreDestructor(RegistrationType instance) { - void delegate() preDestructor = null; - foreach (memberName; __traits(allMembers, RegistrationType)) { - mixin(createImportsString!RegistrationType); - static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) - && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" - && isFunction!(mixin(fullyQualifiedName!RegistrationType ~ `.` ~ memberName)) - && hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) { - preDestructor = &__traits(getMember, instance, memberName); - } - } + private void delegate() getPreDestructor(RegistrationType instance) { + void delegate() preDestructor = null; + foreach (memberName; __traits(allMembers, RegistrationType)) { + mixin(createImportsString!RegistrationType); + static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) + && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" + && isFunction!(mixin(fullyQualifiedName!RegistrationType ~ `.` ~ memberName)) + && hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) { + preDestructor = &__traits(getMember, instance, memberName); + } + } - return preDestructor; - } + return preDestructor; + } } class AutowireInstantiationContext : InstantiationContext { - public bool autowireInstance = true; + public bool autowireInstance = true; } diff --git a/source/poodinis/container.d b/source/poodinis/container.d index 86a7102..91949dc 100644 --- a/source/poodinis/container.d +++ b/source/poodinis/container.d @@ -5,7 +5,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -27,60 +27,60 @@ import std.concurrency; import std.traits; debug { - import std.stdio; + import std.stdio; } /** * Exception thrown when errors occur while resolving a type in a dependency container. */ class ResolveException : Exception { - this(string message, TypeInfo resolveType) { - super(format("Exception while resolving type %s: %s", resolveType.toString(), message)); - } + this(string message, TypeInfo resolveType) { + super(format("Exception while resolving type %s: %s", resolveType.toString(), message)); + } - this(Throwable cause, TypeInfo resolveType) { - super(format("Exception while resolving type %s", resolveType.toString()), cause); - } + this(Throwable cause, TypeInfo resolveType) { + super(format("Exception while resolving type %s", resolveType.toString()), cause); + } } /** * Exception thrown when errors occur while registering a type in a dependency container. */ class RegistrationException : Exception { - this(string message, TypeInfo registrationType) { - super(format("Exception while registering type %s: %s", registrationType.toString(), message)); - } + this(string message, TypeInfo registrationType) { + super(format("Exception while registering type %s: %s", registrationType.toString(), message)); + } } /** * Options which influence the process of registering dependencies */ public enum RegistrationOption { - none = 0, - /** - * Prevent a concrete type being registered on itself. With this option you will always need - * to use the supertype as the type of the dependency. - */ - doNotAddConcreteTypeRegistration = 1 << 0, + none = 0, + /** + * Prevent a concrete type being registered on itself. With this option you will always need + * to use the supertype as the type of the dependency. + */ + doNotAddConcreteTypeRegistration = 1 << 0, } /** * Options which influence the process of resolving dependencies */ public enum ResolveOption { - none = 0, - /** - * Registers the type you're trying to resolve before returning it. - * This essentially makes registration optional for resolving by concerete types. - * Resolinvg will still fail when trying to resolve a dependency by supertype. - */ - registerBeforeResolving = 1 << 0, + none = 0, + /** + * Registers the type you're trying to resolve before returning it. + * This essentially makes registration optional for resolving by concerete types. + * Resolinvg will still fail when trying to resolve a dependency by supertype. + */ + registerBeforeResolving = 1 << 0, - /** - * Does not throw a resolve exception when a type is not registered but will - * return null instead. If the type is an array, an empty array is returned instead. - */ - noResolveException = 1 << 1 + /** + * Does not throw a resolve exception when a type is not registered but will + * return null instead. If the type is an array, an empty array is returned instead. + */ + noResolveException = 1 << 1 } /** @@ -112,358 +112,358 @@ struct PreDestroy {} * You can still create new instances of this class for exceptional situations. */ synchronized class DependencyContainer { - private Registration[][TypeInfo] registrations; + private Registration[][TypeInfo] registrations; - private Registration[] autowireStack; + private Registration[] autowireStack; - private RegistrationOption persistentRegistrationOptions; - private ResolveOption persistentResolveOptions; + private RegistrationOption persistentRegistrationOptions; + private ResolveOption persistentResolveOptions; - ~this() { - clearAllRegistrations(); - } + ~this() { + clearAllRegistrations(); + } - /** - * Register a dependency by concrete class type. - * - * A dependency registered by concrete class type can only be resolved by concrete class type. - * No qualifiers can be used when resolving dependencies which are registered by concrete type. - * - * The default registration scope is "single instance" scope. - * - * Returns: - * A registration is returned which can be used to change the registration scope. - * - * Examples: - * Register and resolve a class by concrete type: - * --- - * class Cat : Animal { ... } - * container.register!Cat; - * --- - * - * See_Also: singleInstance, newInstance, existingInstance - */ - public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) { - return register!(ConcreteType, ConcreteType)(options); - } + /** + * Register a dependency by concrete class type. + * + * A dependency registered by concrete class type can only be resolved by concrete class type. + * No qualifiers can be used when resolving dependencies which are registered by concrete type. + * + * The default registration scope is "single instance" scope. + * + * Returns: + * A registration is returned which can be used to change the registration scope. + * + * Examples: + * Register and resolve a class by concrete type: + * --- + * class Cat : Animal { ... } + * container.register!Cat; + * --- + * + * See_Also: singleInstance, newInstance, existingInstance + */ + public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) { + return register!(ConcreteType, ConcreteType)(options); + } - /** - * Register a dependency by super type. - * - * A dependency registered by super type can only be resolved by super type. A qualifier is typically - * used to resolve dependencies registered by super type. - * - * The default registration scope is "single instance" scope. - * - * Examples: - * Register and resolve by super type - * --- - * class Cat : Animal { ... } - * container.register!(Animal, Cat); - * --- - * - * See_Also: singleInstance, newInstance, existingInstance, RegistrationOption - */ - public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) { - TypeInfo registeredType = typeid(SuperType); - TypeInfo_Class concreteType = typeid(ConcreteType); + /** + * Register a dependency by super type. + * + * A dependency registered by super type can only be resolved by super type. A qualifier is typically + * used to resolve dependencies registered by super type. + * + * The default registration scope is "single instance" scope. + * + * Examples: + * Register and resolve by super type + * --- + * class Cat : Animal { ... } + * container.register!(Animal, Cat); + * --- + * + * See_Also: singleInstance, newInstance, existingInstance, RegistrationOption + */ + public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) { + TypeInfo registeredType = typeid(SuperType); + TypeInfo_Class concreteType = typeid(ConcreteType); - debug(poodinisVerbose) { - writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString())); - } + debug(poodinisVerbose) { + writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString())); + } - auto existingRegistration = getExistingRegistration(registeredType, concreteType); - if (existingRegistration) { - return existingRegistration; - } + auto existingRegistration = getExistingRegistration(registeredType, concreteType); + if (existingRegistration) { + return existingRegistration; + } - auto instanceFactory = new ConstructorInjectingInstanceFactory!ConcreteType(this); - auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this); - newRegistration.singleInstance(); + auto instanceFactory = new ConstructorInjectingInstanceFactory!ConcreteType(this); + auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this); + newRegistration.singleInstance(); - static if (!is(SuperType == ConcreteType)) { - if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) { - auto concreteTypeRegistration = register!ConcreteType; - concreteTypeRegistration.linkTo(newRegistration); - } - } + static if (!is(SuperType == ConcreteType)) { + if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) { + auto concreteTypeRegistration = register!ConcreteType; + concreteTypeRegistration.linkTo(newRegistration); + } + } - registrations[registeredType] ~= cast(shared(Registration)) newRegistration; - return newRegistration; - } + registrations[registeredType] ~= cast(shared(Registration)) newRegistration; + return newRegistration; + } - private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) { - return ((options | persistentOptions) & option) != 0; - } + private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) { + return ((options | persistentOptions) & option) != 0; + } - private OptionType buildFlags(OptionType)(OptionType[] options) { - OptionType flags; - foreach (option; options) { - flags |= option; - } - return flags; - } + private OptionType buildFlags(OptionType)(OptionType[] options) { + OptionType flags; + foreach (option; options) { + flags |= option; + } + return flags; + } - private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) { - auto existingCandidates = registrationType in registrations; - if (existingCandidates) { - return getRegistration(cast(Registration[]) *existingCandidates, qualifierType); - } + private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) { + auto existingCandidates = registrationType in registrations; + if (existingCandidates) { + return getRegistration(cast(Registration[]) *existingCandidates, qualifierType); + } - return null; - } + return null; + } - private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) { - foreach(existingRegistration ; candidates) { - if (existingRegistration.instanceType == concreteType) { - return existingRegistration; - } - } + private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) { + foreach(existingRegistration ; candidates) { + if (existingRegistration.instanceType == concreteType) { + return existingRegistration; + } + } - return null; - } + return null; + } - /** - * Resolve dependencies. - * - * Dependencies can only resolved using this method if they are registered by concrete type or the only - * concrete type registered by super type. - * - * Resolved dependencies are automatically autowired before being returned. - * - * Returns: - * An instance is returned which is created according to the registration scope with which they are registered. - * - * Throws: - * ResolveException when type is not registered. - * - * Examples: - * Resolve dependencies registered by super type and concrete type: - * --- - * class Cat : Animal { ... } - * class Dog : Animal { ... } - * - * container.register!(Animal, Cat); - * container.register!Dog; - * - * container.resolve!Animal; - * container.resolve!Dog; - * --- - * You cannot resolve a dependency when it is registered by multiple super types: - * --- - * class Cat : Animal { ... } - * class Dog : Animal { ... } - * - * container.register!(Animal, Cat); - * container.register!(Animal, Dog); - * - * container.resolve!Animal; // Error: multiple candidates for type "Animal" - * container.resolve!Dog; // Error: No type is registered by concrete type "Dog", only by super type "Animal" - * --- - * You need to use the resolve method which allows you to specify a qualifier. - */ - public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { - return resolve!(RegistrationType, RegistrationType)(resolveOptions); - } + /** + * Resolve dependencies. + * + * Dependencies can only resolved using this method if they are registered by concrete type or the only + * concrete type registered by super type. + * + * Resolved dependencies are automatically autowired before being returned. + * + * Returns: + * An instance is returned which is created according to the registration scope with which they are registered. + * + * Throws: + * ResolveException when type is not registered. + * + * Examples: + * Resolve dependencies registered by super type and concrete type: + * --- + * class Cat : Animal { ... } + * class Dog : Animal { ... } + * + * container.register!(Animal, Cat); + * container.register!Dog; + * + * container.resolve!Animal; + * container.resolve!Dog; + * --- + * You cannot resolve a dependency when it is registered by multiple super types: + * --- + * class Cat : Animal { ... } + * class Dog : Animal { ... } + * + * container.register!(Animal, Cat); + * container.register!(Animal, Dog); + * + * container.resolve!Animal; // Error: multiple candidates for type "Animal" + * container.resolve!Dog; // Error: No type is registered by concrete type "Dog", only by super type "Animal" + * --- + * You need to use the resolve method which allows you to specify a qualifier. + */ + public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { + return resolve!(RegistrationType, RegistrationType)(resolveOptions); + } - /** - * Resolve dependencies using a qualifier. - * - * Dependencies can only resolved using this method if they are registered by super type. - * - * Resolved dependencies are automatically autowired before being returned. - * - * Returns: - * An instance is returned which is created according to the registration scope with which they are registered. - * - * Throws: - * ResolveException when type is not registered or there are multiple candidates available for type. - * - * Examples: - * Resolve dependencies registered by super type: - * --- - * class Cat : Animal { ... } - * class Dog : Animal { ... } - * - * container.register!(Animal, Cat); - * container.register!(Animal, Dog); - * - * container.resolve!(Animal, Cat); - * container.resolve!(Animal, Dog); - * --- - */ - public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { - TypeInfo resolveType = typeid(RegistrationType); - TypeInfo qualifierType = typeid(QualifierType); + /** + * Resolve dependencies using a qualifier. + * + * Dependencies can only resolved using this method if they are registered by super type. + * + * Resolved dependencies are automatically autowired before being returned. + * + * Returns: + * An instance is returned which is created according to the registration scope with which they are registered. + * + * Throws: + * ResolveException when type is not registered or there are multiple candidates available for type. + * + * Examples: + * Resolve dependencies registered by super type: + * --- + * class Cat : Animal { ... } + * class Dog : Animal { ... } + * + * container.register!(Animal, Cat); + * container.register!(Animal, Dog); + * + * container.resolve!(Animal, Cat); + * container.resolve!(Animal, Dog); + * --- + */ + public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { + TypeInfo resolveType = typeid(RegistrationType); + TypeInfo qualifierType = typeid(QualifierType); - debug(poodinisVerbose) { - writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString()); - } + debug(poodinisVerbose) { + writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString()); + } - static if (__traits(compiles, new QualifierType())) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.registerBeforeResolving)) { - register!(RegistrationType, QualifierType)(); - } - } + static if (__traits(compiles, new QualifierType())) { + if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.registerBeforeResolving)) { + register!(RegistrationType, QualifierType)(); + } + } - auto candidates = resolveType in registrations; - if (!candidates) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { - return null; - } + auto candidates = resolveType in registrations; + if (!candidates) { + if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { + return null; + } - throw new ResolveException("Type not registered.", resolveType); - } + throw new ResolveException("Type not registered.", resolveType); + } - Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates); + Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates); - try { - QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration); - callPostConstructors(newInstance); - return newInstance; - } catch (ValueInjectionException e) { - throw new ResolveException(e, resolveType); - } - } + try { + QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration); + callPostConstructors(newInstance); + return newInstance; + } catch (ValueInjectionException e) { + throw new ResolveException(e, resolveType); + } + } - private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) { - QualifierType instance; - if (!(cast(Registration[]) autowireStack).canFind(registration)) { - autowireStack ~= cast(shared(Registration)) registration; - instance = cast(QualifierType) registration.getInstance(new AutowireInstantiationContext()); - autowireStack = autowireStack[0 .. $-1]; - } else { - auto autowireContext = new AutowireInstantiationContext(); - autowireContext.autowireInstance = false; - instance = cast(QualifierType) registration.getInstance(autowireContext); - } - return instance; - } + private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) { + QualifierType instance; + if (!(cast(Registration[]) autowireStack).canFind(registration)) { + autowireStack ~= cast(shared(Registration)) registration; + instance = cast(QualifierType) registration.getInstance(new AutowireInstantiationContext()); + autowireStack = autowireStack[0 .. $-1]; + } else { + auto autowireContext = new AutowireInstantiationContext(); + autowireContext.autowireInstance = false; + instance = cast(QualifierType) registration.getInstance(autowireContext); + } + return instance; + } - /** - * Resolve all dependencies registered to a super type. - * - * Returns: - * An array of autowired instances is returned. The order is undetermined. - * - * Examples: - * --- - * class Cat : Animal { ... } - * class Dog : Animal { ... } - * - * container.register!(Animal, Cat); - * container.register!(Animal, Dog); - * - * Animal[] animals = container.resolveAll!Animal; - * --- - */ - public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { - RegistrationType[] instances; - TypeInfo resolveType = typeid(RegistrationType); + /** + * Resolve all dependencies registered to a super type. + * + * Returns: + * An array of autowired instances is returned. The order is undetermined. + * + * Examples: + * --- + * class Cat : Animal { ... } + * class Dog : Animal { ... } + * + * container.register!(Animal, Cat); + * container.register!(Animal, Dog); + * + * Animal[] animals = container.resolveAll!Animal; + * --- + */ + public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { + RegistrationType[] instances; + TypeInfo resolveType = typeid(RegistrationType); - auto qualifiedRegistrations = resolveType in registrations; - if (!qualifiedRegistrations) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { - return []; - } + auto qualifiedRegistrations = resolveType in registrations; + if (!qualifiedRegistrations) { + if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { + return []; + } - throw new ResolveException("Type not registered.", resolveType); - } + throw new ResolveException("Type not registered.", resolveType); + } - foreach(registration ; cast(Registration[]) *qualifiedRegistrations) { - instances ~= resolveAutowiredInstance!RegistrationType(registration); - } + foreach(registration ; cast(Registration[]) *qualifiedRegistrations) { + instances ~= resolveAutowiredInstance!RegistrationType(registration); + } - return instances; - } + return instances; + } - private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) { - if (resolveType == qualifierType) { - if (candidates.length > 1) { - string candidateList = candidates.toConcreteTypeListString(); - throw new ResolveException("Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.", resolveType); - } + private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) { + if (resolveType == qualifierType) { + if (candidates.length > 1) { + string candidateList = candidates.toConcreteTypeListString(); + throw new ResolveException("Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.", resolveType); + } - return candidates[0]; - } + return candidates[0]; + } - return getRegistration(candidates, qualifierType); - } + return getRegistration(candidates, qualifierType); + } - private void callPostConstructors(Type)(Type instance) { - foreach (memberName; __traits(allMembers, Type)) { - mixin(createImportsString!Type); + private void callPostConstructors(Type)(Type instance) { + foreach (memberName; __traits(allMembers, Type)) { + mixin(createImportsString!Type); - static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) - && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" - && isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName)) - && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) { - __traits(getMember, instance, memberName)(); - } - } - } + static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) + && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" + && isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName)) + && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) { + __traits(getMember, instance, memberName)(); + } + } + } - /** - * Clears all dependency registrations managed by this container. - */ - public void clearAllRegistrations() { - foreach(registrationsOfType; registrations) { - callPreDestructorsOfRegistrations(registrationsOfType); - } - registrations.destroy(); - } + /** + * Clears all dependency registrations managed by this container. + */ + public void clearAllRegistrations() { + foreach(registrationsOfType; registrations) { + callPreDestructorsOfRegistrations(registrationsOfType); + } + registrations.destroy(); + } - /** - * Removes a registered dependency by type. - * - * A dependency can be removed either by super type or concrete type, depending on how they are registered. - * - * Examples: - * --- - * container.removeRegistration!Animal; - * --- - */ - public void removeRegistration(RegistrationType)() { - auto registrationsOfType = *(typeid(RegistrationType) in registrations); - callPreDestructorsOfRegistrations(registrationsOfType); - registrations.remove(typeid(RegistrationType)); - } + /** + * Removes a registered dependency by type. + * + * A dependency can be removed either by super type or concrete type, depending on how they are registered. + * + * Examples: + * --- + * container.removeRegistration!Animal; + * --- + */ + public void removeRegistration(RegistrationType)() { + auto registrationsOfType = *(typeid(RegistrationType) in registrations); + callPreDestructorsOfRegistrations(registrationsOfType); + registrations.remove(typeid(RegistrationType)); + } - private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) { - foreach(registration; registrations) { - Registration unsharedRegistration = cast(Registration) registration; - if (unsharedRegistration.preDestructor !is null) { - unsharedRegistration.preDestructor()(); - } - } - } + private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) { + foreach(registration; registrations) { + Registration unsharedRegistration = cast(Registration) registration; + if (unsharedRegistration.preDestructor !is null) { + unsharedRegistration.preDestructor()(); + } + } + } - /** - * Apply persistent registration options which will be used everytime register() is called. - */ - public void setPersistentRegistrationOptions(RegistrationOption options) { - persistentRegistrationOptions = options; - } + /** + * Apply persistent registration options which will be used everytime register() is called. + */ + public void setPersistentRegistrationOptions(RegistrationOption options) { + persistentRegistrationOptions = options; + } - /** - * Unsets all applied persistent registration options - */ - public void unsetPersistentRegistrationOptions() { - persistentRegistrationOptions = RegistrationOption.none; - } + /** + * Unsets all applied persistent registration options + */ + public void unsetPersistentRegistrationOptions() { + persistentRegistrationOptions = RegistrationOption.none; + } - /** - * Apply persistent resolve options which will be used everytime resolve() is called. - */ - public void setPersistentResolveOptions(ResolveOption options) { - persistentResolveOptions = options; - } + /** + * Apply persistent resolve options which will be used everytime resolve() is called. + */ + public void setPersistentResolveOptions(ResolveOption options) { + persistentResolveOptions = options; + } - /** - * Unsets all applied persistent resolve options - */ - public void unsetPersistentResolveOptions() { - persistentResolveOptions = ResolveOption.none; - } + /** + * Unsets all applied persistent resolve options + */ + public void unsetPersistentResolveOptions() { + persistentResolveOptions = ResolveOption.none; + } } diff --git a/source/poodinis/context.d b/source/poodinis/context.d index 3d3e865..199a506 100644 --- a/source/poodinis/context.d +++ b/source/poodinis/context.d @@ -5,7 +5,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -21,7 +21,7 @@ import poodinis.autowire; import std.traits; class ApplicationContext { - public void registerDependencies(shared(DependencyContainer) container) {} + public void registerDependencies(shared(DependencyContainer) container) {} } /** @@ -35,7 +35,7 @@ struct Component {} * enables you to use type-qualified alternatives for dependencies. */ struct RegisterByType(Type) { - Type type; + Type type; } /** @@ -52,33 +52,33 @@ struct Prototype {} * want to use annotations to set-up dependencies in your classes. */ public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) { - auto context = new Context(); - context.registerDependencies(container); - context.registerContextComponents(container); - container.register!(ApplicationContext, Context)().existingInstance(context); - autowire(container, context); + auto context = new Context(); + context.registerDependencies(container); + context.registerContextComponents(container); + container.register!(ApplicationContext, Context)().existingInstance(context); + autowire(container, context); } public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) { - foreach (member ; __traits(allMembers, ApplicationContextType)) { - static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) { - auto factoryMethod = &__traits(getMember, context, member); - Registration registration = null; - auto createsSingleton = CreatesSingleton.yes; + foreach (member ; __traits(allMembers, ApplicationContextType)) { + static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) { + auto factoryMethod = &__traits(getMember, context, member); + Registration registration = null; + auto createsSingleton = CreatesSingleton.yes; - foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) { - static if (is(attribute == RegisterByType!T, T)) { - registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod); - } else static if (__traits(isSame, attribute, Prototype)) { - createsSingleton = CreatesSingleton.no; - } - } + foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) { + static if (is(attribute == RegisterByType!T, T)) { + registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod); + } else static if (__traits(isSame, attribute, Prototype)) { + createsSingleton = CreatesSingleton.no; + } + } - if (registration is null) { - registration = container.register!(ReturnType!factoryMethod); - } + if (registration is null) { + registration = container.register!(ReturnType!factoryMethod); + } - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod); - } - } + registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod); + } + } } diff --git a/source/poodinis/factory.d b/source/poodinis/factory.d index 4103978..b6bd017 100644 --- a/source/poodinis/factory.d +++ b/source/poodinis/factory.d @@ -3,7 +3,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -24,147 +24,147 @@ alias CreatesSingleton = Flag!"CreatesSingleton"; alias InstanceFactoryMethod = Object delegate(); class InstanceCreationException : Exception { - this(string message, string file = __FILE__, size_t line = __LINE__) { - super(message, file, line); - } + this(string message, string file = __FILE__, size_t line = __LINE__) { + super(message, file, line); + } } struct InstanceFactoryParameters { - TypeInfo_Class instanceType; - CreatesSingleton createsSingleton = CreatesSingleton.yes; - Object existingInstance; - InstanceFactoryMethod factoryMethod; + TypeInfo_Class instanceType; + CreatesSingleton createsSingleton = CreatesSingleton.yes; + Object existingInstance; + InstanceFactoryMethod factoryMethod; } class InstanceFactory { - private Object instance = null; - private InstanceFactoryParameters _factoryParameters; + private Object instance = null; + private InstanceFactoryParameters _factoryParameters; - this() { - factoryParameters = InstanceFactoryParameters(); - } + this() { + factoryParameters = InstanceFactoryParameters(); + } - public @property void factoryParameters(InstanceFactoryParameters factoryParameters) { - if (factoryParameters.factoryMethod is null) { - factoryParameters.factoryMethod = &this.createInstance; - } + public @property void factoryParameters(InstanceFactoryParameters factoryParameters) { + if (factoryParameters.factoryMethod is null) { + factoryParameters.factoryMethod = &this.createInstance; + } - if (factoryParameters.existingInstance !is null) { - factoryParameters.createsSingleton = CreatesSingleton.yes; - this.instance = factoryParameters.existingInstance; - } + if (factoryParameters.existingInstance !is null) { + factoryParameters.createsSingleton = CreatesSingleton.yes; + this.instance = factoryParameters.existingInstance; + } - _factoryParameters = factoryParameters; - } + _factoryParameters = factoryParameters; + } - public @property InstanceFactoryParameters factoryParameters() { - return _factoryParameters; - } + public @property InstanceFactoryParameters factoryParameters() { + return _factoryParameters; + } - public Object getInstance() { - if (_factoryParameters.createsSingleton && instance !is null) { - debug(poodinisVerbose) { - printDebugUseExistingInstance(); - } + public Object getInstance() { + if (_factoryParameters.createsSingleton && instance !is null) { + debug(poodinisVerbose) { + printDebugUseExistingInstance(); + } - return instance; - } + return instance; + } - debug(poodinisVerbose) { - printDebugCreateNewInstance(); - } + debug(poodinisVerbose) { + printDebugCreateNewInstance(); + } - instance = _factoryParameters.factoryMethod(); - return instance; - } + instance = _factoryParameters.factoryMethod(); + return instance; + } - private void printDebugUseExistingInstance() { - if (_factoryParameters.instanceType !is null) { - writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString())); - } else { - writeln("DEBUG: Existing instance returned from custom factory method"); - } - } + private void printDebugUseExistingInstance() { + if (_factoryParameters.instanceType !is null) { + writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString())); + } else { + writeln("DEBUG: Existing instance returned from custom factory method"); + } + } - private void printDebugCreateNewInstance() { - if (_factoryParameters.instanceType !is null) { - writeln(format("DEBUG: Creating new instance of type %s", _factoryParameters.instanceType.toString())); - } else { - writeln("DEBUG: Creating new instance from custom factory method"); - } - } + private void printDebugCreateNewInstance() { + if (_factoryParameters.instanceType !is null) { + writeln(format("DEBUG: Creating new instance of type %s", _factoryParameters.instanceType.toString())); + } else { + writeln("DEBUG: Creating new instance from custom factory method"); + } + } - protected Object createInstance() { - enforce!InstanceCreationException(_factoryParameters.instanceType, "Instance type is not defined, cannot create instance without knowing its type."); - return _factoryParameters.instanceType.create(); - } + protected Object createInstance() { + enforce!InstanceCreationException(_factoryParameters.instanceType, "Instance type is not defined, cannot create instance without knowing its type."); + return _factoryParameters.instanceType.create(); + } } class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory { - private shared DependencyContainer container; - private bool isBeingInjected = false; + private shared DependencyContainer container; + private bool isBeingInjected = false; - this(shared DependencyContainer container) { - this.container = container; - } + this(shared DependencyContainer container) { + this.container = container; + } - private static string createArgumentList(Params...)() { - string argumentList = ""; - foreach(param; Params) { - if (argumentList.length > 0) { - argumentList ~= ","; - } + private static string createArgumentList(Params...)() { + string argumentList = ""; + foreach(param; Params) { + if (argumentList.length > 0) { + argumentList ~= ","; + } - argumentList ~= "container.resolve!" ~ param.stringof; - } - return argumentList; - } + argumentList ~= "container.resolve!" ~ param.stringof; + } + return argumentList; + } - private static string createImportList(Params...)() { - string importList = ""; - foreach(param; Params) { - importList ~= createImportsString!param; - } - return importList; - } + private static string createImportList(Params...)() { + string importList = ""; + foreach(param; Params) { + importList ~= createImportsString!param; + } + return importList; + } - private static bool parametersAreValid(Params...)() { - bool isValid = true; - foreach(param; Params) { - if (isBuiltinType!param) { - isValid = false; - break; - } - } + private static bool parametersAreValid(Params...)() { + bool isValid = true; + foreach(param; Params) { + if (isBuiltinType!param) { + isValid = false; + break; + } + } - return isValid; - } + return isValid; + } - protected override Object createInstance() { - enforce!InstanceCreationException(container, "A dependency container is not defined. Cannot perform constructor injection without one."); - enforce!InstanceCreationException(!isBeingInjected, format("%s is already being created and injected; possible circular dependencies in constructors?", InstanceType.stringof)); + protected override Object createInstance() { + enforce!InstanceCreationException(container, "A dependency container is not defined. Cannot perform constructor injection without one."); + enforce!InstanceCreationException(!isBeingInjected, format("%s is already being created and injected; possible circular dependencies in constructors?", InstanceType.stringof)); - Object instance = null; - static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) { - foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) { - static if (parametersAreValid!(Parameters!ctor)) { - isBeingInjected = true; - mixin(createImportsString!InstanceType - ~ createImportList!(Parameters!ctor) ~ ` - instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `); - `); - isBeingInjected = false; - break; - } - } - } + Object instance = null; + static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) { + foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) { + static if (parametersAreValid!(Parameters!ctor)) { + isBeingInjected = true; + mixin(createImportsString!InstanceType + ~ createImportList!(Parameters!ctor) ~ ` + instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `); + `); + isBeingInjected = false; + break; + } + } + } - if (instance is null) { - instance = typeid(InstanceType).create(); - } + if (instance is null) { + instance = typeid(InstanceType).create(); + } - enforce!InstanceCreationException(instance !is null, "Unable to create instance of type" ~ InstanceType.stringof ~ ", does it have injectable constructors?"); + enforce!InstanceCreationException(instance !is null, "Unable to create instance of type" ~ InstanceType.stringof ~ ", does it have injectable constructors?"); - return instance; - } + return instance; + } } diff --git a/source/poodinis/imports.d b/source/poodinis/imports.d index 0e4a152..107b278 100644 --- a/source/poodinis/imports.d +++ b/source/poodinis/imports.d @@ -1,16 +1,27 @@ +/** + * This module contains instance factory facilities + * + * Authors: + * Mike Bierlee, m.bierlee@lostmoment.com + * Copyright: 2014-2018 Mike Bierlee + * License: + * This software is licensed under the terms of the MIT license. + * The full terms of the license can be found in the LICENSE file. + */ + module poodinis.imports; import std.traits; public static string createImportsString(Type)() { - string imports = `import ` ~ moduleName!Type ~ `;`; - static if (__traits(compiles, TemplateArgsOf!Type)) { - foreach(TemplateArgType; TemplateArgsOf!Type) { - static if (!isBuiltinType!TemplateArgType) { - imports ~= createImportsString!TemplateArgType; - } - } - } + string imports = `import ` ~ moduleName!Type ~ `;`; + static if (__traits(compiles, TemplateArgsOf!Type)) { + foreach(TemplateArgType; TemplateArgsOf!Type) { + static if (!isBuiltinType!TemplateArgType) { + imports ~= createImportsString!TemplateArgType; + } + } + } - return imports; + return imports; } \ No newline at end of file diff --git a/source/poodinis/package.d b/source/poodinis/package.d index ef511ba..ab9a39e 100644 --- a/source/poodinis/package.d +++ b/source/poodinis/package.d @@ -3,7 +3,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. diff --git a/source/poodinis/polyfill.d b/source/poodinis/polyfill.d index 5bd5fd7..4140031 100644 --- a/source/poodinis/polyfill.d +++ b/source/poodinis/polyfill.d @@ -19,7 +19,7 @@ * Kenji Hara, * Shoichi Kato, * Mike Bierlee (m.bierlee@lostmoment.com) - * Copyright: Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2017 Mike Bierlee + * Copyright: Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2018 Mike Bierlee * License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0) */ @@ -29,35 +29,35 @@ import std.exception; import std.traits; static if (!__traits(compiles, basicExceptionCtors)) { - mixin template basicExceptionCtors() - { - this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @safe pure nothrow - { - super(msg, file, line, next); - } + mixin template basicExceptionCtors() + { + this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @safe pure nothrow + { + super(msg, file, line, next); + } - this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow - { - super(msg, file, line, next); - } - } + this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow + { + super(msg, file, line, next); + } + } } static if (!__traits(compiles, isFunction)) { - template isFunction(X...) if (X.length == 1) - { - static if (is(typeof(&X[0]) U : U*) && is(U == function) || - is(typeof(&X[0]) U == delegate)) - { - // x is a (nested) function symbol. - enum isFunction = true; - } - else static if (is(X[0] T)) - { - // x is a type. Take the type of it and examine. - enum isFunction = is(T == function); - } - else - enum isFunction = false; - } + template isFunction(X...) if (X.length == 1) + { + static if (is(typeof(&X[0]) U : U*) && is(U == function) || + is(typeof(&X[0]) U == delegate)) + { + // x is a (nested) function symbol. + enum isFunction = true; + } + else static if (is(X[0] T)) + { + // x is a type. Take the type of it and examine. + enum isFunction = is(T == function); + } + else + enum isFunction = false; + } } diff --git a/source/poodinis/registration.d b/source/poodinis/registration.d index d530d89..c841c2b 100644 --- a/source/poodinis/registration.d +++ b/source/poodinis/registration.d @@ -5,7 +5,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -17,61 +17,61 @@ import poodinis.container; import poodinis.factory; class Registration { - private TypeInfo _registeredType = null; - private TypeInfo_Class _instanceType = null; - private Registration linkedRegistration; - private shared(DependencyContainer) _originatingContainer; - private InstanceFactory _instanceFactory; - private void delegate() _preDestructor; + private TypeInfo _registeredType = null; + private TypeInfo_Class _instanceType = null; + private Registration linkedRegistration; + private shared(DependencyContainer) _originatingContainer; + private InstanceFactory _instanceFactory; + private void delegate() _preDestructor; - public @property registeredType() { - return _registeredType; - } + public @property registeredType() { + return _registeredType; + } - public @property instanceType() { - return _instanceType; - } + public @property instanceType() { + return _instanceType; + } - public @property originatingContainer() { - return _originatingContainer; - } + public @property originatingContainer() { + return _originatingContainer; + } - public @property instanceFactory() { - return _instanceFactory; - } + public @property instanceFactory() { + return _instanceFactory; + } - public @property preDestructor() { - return _preDestructor; - } + public @property preDestructor() { + return _preDestructor; + } - protected @property preDestructor(void delegate() preDestructor) { - _preDestructor = preDestructor; - } + protected @property preDestructor(void delegate() preDestructor) { + _preDestructor = preDestructor; + } - this(TypeInfo registeredType, TypeInfo_Class instanceType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { - this._registeredType = registeredType; - this._instanceType = instanceType; - this._originatingContainer = originatingContainer; - this._instanceFactory = instanceFactory; - } + this(TypeInfo registeredType, TypeInfo_Class instanceType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { + this._registeredType = registeredType; + this._instanceType = instanceType; + this._originatingContainer = originatingContainer; + this._instanceFactory = instanceFactory; + } - public Object getInstance(InstantiationContext context = new InstantiationContext()) { - if (linkedRegistration !is null) { - return linkedRegistration.getInstance(context); - } + public Object getInstance(InstantiationContext context = new InstantiationContext()) { + if (linkedRegistration !is null) { + return linkedRegistration.getInstance(context); + } - if (instanceFactory is null) { - throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString()); - } + if (instanceFactory is null) { + throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString()); + } - return instanceFactory.getInstance(); - } + return instanceFactory.getInstance(); + } - public Registration linkTo(Registration registration) { - this.linkedRegistration = registration; - return this; - } + public Registration linkTo(Registration registration) { + this.linkedRegistration = registration; + return this; + } } /** @@ -80,35 +80,35 @@ class Registration { * Effectively makes the given registration a singleton. */ public Registration singleInstance(Registration registration) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes); - return registration; + registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes); + return registration; } /** * Scopes registrations to return a new instance every time the given registration is resolved. */ public Registration newInstance(Registration registration) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no); - return registration; + registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no); + return registration; } /** * Scopes registrations to return the given instance every time the given registration is resolved. */ public Registration existingInstance(Registration registration, Object instance) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, instance); - return registration; + registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, instance); + return registration; } public string toConcreteTypeListString(Registration[] registrations) { - auto concreteTypeListString = ""; - foreach (registration ; registrations) { - if (concreteTypeListString.length > 0) { - concreteTypeListString ~= ", "; - } - concreteTypeListString ~= registration.instanceType.toString(); - } - return concreteTypeListString; + auto concreteTypeListString = ""; + foreach (registration ; registrations) { + if (concreteTypeListString.length > 0) { + concreteTypeListString ~= ", "; + } + concreteTypeListString ~= registration.instanceType.toString(); + } + return concreteTypeListString; } class InstantiationContext {} diff --git a/source/poodinis/valueinjection.d b/source/poodinis/valueinjection.d index c75a3a3..983ac6b 100644 --- a/source/poodinis/valueinjection.d +++ b/source/poodinis/valueinjection.d @@ -4,7 +4,7 @@ * * Authors: * Mike Bierlee, m.bierlee@lostmoment.com - * Copyright: 2014-2017 Mike Bierlee + * Copyright: 2014-2018 Mike Bierlee * License: * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. @@ -19,20 +19,20 @@ import poodinis.polyfill; * Thrown when something goes wrong during value injection. */ class ValueInjectionException : Exception { - mixin basicExceptionCtors; + mixin basicExceptionCtors; } /** * Thrown by injectors when the value with the given key cannot be found. */ class ValueNotAvailableException : Exception { - this(string key) { - super(format("Value for key %s is not available", key)); - } + this(string key) { + super(format("Value for key %s is not available", key)); + } - this(string key, Throwable cause) { - super(format("Value for key %s is not available", key), cause); - } + this(string key, Throwable cause) { + super(format("Value for key %s is not available", key), cause); + } } /** @@ -53,12 +53,12 @@ class ValueNotAvailableException : Exception { * --- */ struct Value { - /** - * The textual key used to find the value by injectors. - * - * The format is injector-specific. - */ - string key; + /** + * The textual key used to find the value by injectors. + * + * The format is injector-specific. + */ + string key; } /** @@ -79,12 +79,12 @@ struct Value { * --- */ struct MandatoryValue { - /** - * The textual key used to find the value by injectors. - * - * The format is injector-specific. - */ - string key; + /** + * The textual key used to find the value by injectors. + * + * The format is injector-specific. + */ + string key; } /** @@ -110,14 +110,14 @@ struct MandatoryValue { * --- */ interface ValueInjector(Type) { - /** - * Get a value from the injector by key. - * - * The key can have any format. Generally you are encouraged - * to accept a dot separated path, for example: server.http.port - * - * Throws: ValueNotAvailableException when the value for the given key is not available for any reason - */ - Type get(string key); + /** + * Get a value from the injector by key. + * + * The key can have any format. Generally you are encouraged + * to accept a dot separated path, for example: server.http.port + * + * Throws: ValueNotAvailableException when the value for the given key is not available for any reason + */ + Type get(string key); } diff --git a/test/poodinis/autowiretest.d b/test/poodinis/autowiretest.d index 5008b82..50450c3 100644 --- a/test/poodinis/autowiretest.d +++ b/test/poodinis/autowiretest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -12,171 +12,171 @@ import std.exception; version(unittest) { - // Test autowiring concrete type to existing instance - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentA; - auto componentB = new ComponentB(); - container.autowire(componentB); - assert(componentB !is null, "Autowirable dependency failed to autowire"); - } + // Test autowiring concrete type to existing instance + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentA; + auto componentB = new ComponentB(); + container.autowire(componentB); + assert(componentB !is null, "Autowirable dependency failed to autowire"); + } - // Test autowiring interface type to existing instance - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC); - auto componentD = new ComponentD(); - container.autowire(componentD); - assert(componentD.componentC !is null, "Autowirable dependency failed to autowire"); - } + // Test autowiring interface type to existing instance + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC); + auto componentD = new ComponentD(); + container.autowire(componentD); + assert(componentD.componentC !is null, "Autowirable dependency failed to autowire"); + } - // Test autowiring private members - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC); - auto componentD = new ComponentD(); - container.autowire(componentD); - assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed"); - } + // Test autowiring private members + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC); + auto componentD = new ComponentD(); + container.autowire(componentD); + assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed"); + } - // Test autowiring will only happen once - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC).newInstance(); - auto componentD = new ComponentD(); - container.autowire(componentD); - auto expectedComponent = componentD.componentC; - container.autowire(componentD); - auto actualComponent = componentD.componentC; - assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance"); - } + // Test autowiring will only happen once + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC).newInstance(); + auto componentD = new ComponentD(); + container.autowire(componentD); + auto expectedComponent = componentD.componentC; + container.autowire(componentD); + auto actualComponent = componentD.componentC; + assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance"); + } - // Test autowiring unregistered type - unittest { - auto container = new shared DependencyContainer(); - auto componentD = new ComponentD(); - assertThrown!(ResolveException)(container.autowire(componentD), "Autowiring unregistered type should throw ResolveException"); - } + // Test autowiring unregistered type + unittest { + auto container = new shared DependencyContainer(); + auto componentD = new ComponentD(); + assertThrown!(ResolveException)(container.autowire(componentD), "Autowiring unregistered type should throw ResolveException"); + } - // Test autowiring member with non-autowire attribute does not autowire - unittest { - auto container = new shared DependencyContainer(); - auto componentE = new ComponentE(); - container.autowire(componentE); - assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire"); - } + // Test autowiring member with non-autowire attribute does not autowire + unittest { + auto container = new shared DependencyContainer(); + auto componentE = new ComponentE(); + container.autowire(componentE); + assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire"); + } - // Test autowire class with alias declaration - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentA; - auto componentDeclarationCocktail = new ComponentDeclarationCocktail(); + // Test autowire class with alias declaration + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentA; + auto componentDeclarationCocktail = new ComponentDeclarationCocktail(); - container.autowire(componentDeclarationCocktail); + container.autowire(componentDeclarationCocktail); - assert(componentDeclarationCocktail.componentA !is null, "Autowiring class with non-assignable declarations failed"); - } + assert(componentDeclarationCocktail.componentA !is null, "Autowiring class with non-assignable declarations failed"); + } - // Test autowire class with qualifier - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC); - container.register!(InterfaceA, ComponentX); - auto componentX = container.resolve!(InterfaceA, ComponentX); + // Test autowire class with qualifier + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC); + container.register!(InterfaceA, ComponentX); + auto componentX = container.resolve!(InterfaceA, ComponentX); - auto monkeyShine = new MonkeyShine(); - container.autowire(monkeyShine); + auto monkeyShine = new MonkeyShine(); + container.autowire(monkeyShine); - assert(monkeyShine.component is componentX, "Autowiring class with qualifier failed"); - } + assert(monkeyShine.component is componentX, "Autowiring class with qualifier failed"); + } - // Test autowire class with multiple qualifiers - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC); - container.register!(InterfaceA, ComponentX); - auto componentC = container.resolve!(InterfaceA, ComponentC); - auto componentX = container.resolve!(InterfaceA, ComponentX); + // Test autowire class with multiple qualifiers + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC); + container.register!(InterfaceA, ComponentX); + auto componentC = container.resolve!(InterfaceA, ComponentC); + auto componentX = container.resolve!(InterfaceA, ComponentX); - auto bootstrapBootstrap = new BootstrapBootstrap(); - container.autowire(bootstrapBootstrap); + auto bootstrapBootstrap = new BootstrapBootstrap(); + container.autowire(bootstrapBootstrap); - assert(bootstrapBootstrap.componentX is componentX, "Autowiring class with multiple qualifiers failed"); - assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed"); - } + assert(bootstrapBootstrap.componentX is componentX, "Autowiring class with multiple qualifiers failed"); + assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed"); + } - // Test getting instance from autowired registration will autowire instance - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentA; + // Test getting instance from autowired registration will autowire instance + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentA; - auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), new InstanceFactory(), container).singleInstance(); - auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext()); + auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), new InstanceFactory(), container).singleInstance(); + auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext()); - assert(instance.componentA !is null); - } + assert(instance.componentA !is null); + } - // Test autowiring a dynamic array with all qualified types - unittest { - auto container = new shared DependencyContainer(); - container.register!(InterfaceA, ComponentC); - container.register!(InterfaceA, ComponentX); + // Test autowiring a dynamic array with all qualified types + unittest { + auto container = new shared DependencyContainer(); + container.register!(InterfaceA, ComponentC); + container.register!(InterfaceA, ComponentX); - auto lord = new LordOfTheComponents(); - container.autowire(lord); + auto lord = new LordOfTheComponents(); + container.autowire(lord); - assert(lord.components.length == 2, "Dynamic array was not autowired"); - } + assert(lord.components.length == 2, "Dynamic array was not autowired"); + } - // Test autowiring new instance of singleinstance registration with newInstance UDA - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentA; + // Test autowiring new instance of singleinstance registration with newInstance UDA + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentA; - auto regularComponentA = container.resolve!ComponentA; - auto charlie = new ComponentCharlie(); + auto regularComponentA = container.resolve!ComponentA; + auto charlie = new ComponentCharlie(); - container.autowire(charlie); + container.autowire(charlie); - assert(charlie.componentA !is regularComponentA, "Autowiring class with AssignNewInstance did not yield a different instance"); - } + assert(charlie.componentA !is regularComponentA, "Autowiring class with AssignNewInstance did not yield a different instance"); + } - // Test autowiring members from base class - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentA; - container.register!ComponentB; - container.register!ComponentZ; + // Test autowiring members from base class + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentA; + container.register!ComponentB; + container.register!ComponentZ; - auto instance = new ComponentZ(); - container.autowire(instance); + auto instance = new ComponentZ(); + container.autowire(instance); - assert(instance.componentA !is null); - } + assert(instance.componentA !is null); + } - // Test autowiring optional dependencies - unittest { - auto container = new shared DependencyContainer(); - auto instance = new OuttaTime(); + // Test autowiring optional dependencies + unittest { + auto container = new shared DependencyContainer(); + auto instance = new OuttaTime(); - container.autowire(instance); + container.autowire(instance); - assert(instance.interfaceA is null); - assert(instance.componentA is null); - assert(instance.componentCs is null); - } + assert(instance.interfaceA is null); + assert(instance.componentA is null); + assert(instance.componentCs is null); + } - // Test autowiring class using value injection - unittest { - auto container = new shared DependencyContainer(); + // Test autowiring class using value injection + unittest { + auto container = new shared DependencyContainer(); - container.register!(ValueInjector!int, TestInjector); - container.register!ComponentA; - auto instance = new ValuedClass(); + container.register!(ValueInjector!int, TestInjector); + container.register!ComponentA; + auto instance = new ValuedClass(); - container.autowire(instance); + container.autowire(instance); - assert(instance.intValue == 8); - assert(instance.unrelated !is null); - } + assert(instance.intValue == 8); + assert(instance.unrelated !is null); + } } diff --git a/test/poodinis/containertest.d b/test/poodinis/containertest.d index 79e3f5e..acb9cec 100644 --- a/test/poodinis/containertest.d +++ b/test/poodinis/containertest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -14,535 +14,535 @@ import core.thread; version(unittest) { - // Test register concrete type - unittest { - auto container = new shared DependencyContainer(); - auto registration = container.register!TestClass; - assert(registration.registeredType == typeid(TestClass), "Type of registered type not the same"); - } - - // Test resolve registered type - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass; - TestClass actualInstance = container.resolve!TestClass; - assert(actualInstance !is null, "Resolved type is null"); - assert(cast(TestClass) actualInstance, "Resolved class is not the same type as expected"); - } - - // Test register interface - unittest { - auto container = new shared DependencyContainer(); - container.register!(TestInterface, TestClass); - TestInterface actualInstance = container.resolve!TestInterface; - assert(actualInstance !is null, "Resolved type is null"); - assert(cast(TestInterface) actualInstance, "Resolved class is not the same type as expected"); - } - - // Test resolve non-registered type - unittest { - auto container = new shared DependencyContainer(); - assertThrown!ResolveException(container.resolve!TestClass, "Resolving non-registered type does not fail"); - } - - // Test clear registrations - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass; - container.clearAllRegistrations(); - assertThrown!ResolveException(container.resolve!TestClass, "Resolving cleared type does not fail"); - } - - // Test resolve single instance for type - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass.singleInstance(); - auto instance1 = container.resolve!TestClass; - auto instance2 = container.resolve!TestClass; - assert(instance1 is instance2, "Resolved instance from single instance scope is not the each time it is resolved"); - } - - // Test resolve new instance for type - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass.newInstance(); - auto instance1 = container.resolve!TestClass; - auto instance2 = container.resolve!TestClass; - assert(instance1 !is instance2, "Resolved instance from new instance scope is the same each time it is resolved"); - } - - // Test resolve existing instance for type - unittest { - auto container = new shared DependencyContainer(); - auto expectedInstance = new TestClass(); - container.register!TestClass.existingInstance(expectedInstance); - auto actualInstance = container.resolve!TestClass; - assert(expectedInstance is actualInstance, "Resolved instance from existing instance scope is not the same as the registered instance"); - } - - // Test autowire resolved instances - unittest { - auto container = new shared DependencyContainer(); - container.register!AutowiredClass; - container.register!ComponentClass; - auto componentInstance = container.resolve!ComponentClass; - auto autowiredInstance = container.resolve!AutowiredClass; - assert(componentInstance.autowiredClass is autowiredInstance, "Member is not autowired upon resolving"); - } - - // Test circular autowiring - unittest { - auto container = new shared DependencyContainer(); - container.register!ComponentMouse; - container.register!ComponentCat; - auto mouse = container.resolve!ComponentMouse; - auto cat = container.resolve!ComponentCat; - assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat, "Circular dependencies should be autowirable"); - } - - // Test remove registration - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass; - container.removeRegistration!TestClass; - assertThrown!ResolveException(container.resolve!TestClass); - } - - // Test autowiring does not autowire member where instance is non-null - unittest { - auto container = new shared DependencyContainer(); - auto existingA = new AutowiredClass(); - auto existingB = new ComponentClass(); - existingB.autowiredClass = existingA; - - container.register!AutowiredClass; - container.register!ComponentClass.existingInstance(existingB); - auto resolvedA = container.resolve!AutowiredClass; - auto resolvedB = container.resolve!ComponentClass; - - assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA, "Autowiring shouldn't rewire member when it is already wired to an instance"); - } - - // Test autowiring circular dependency by third-degree - unittest { - auto container = new shared DependencyContainer(); - container.register!Eenie; - container.register!Meenie; - container.register!Moe; - - auto eenie = container.resolve!Eenie; - - assert(eenie.meenie.moe.eenie is eenie, "Autowiring third-degree circular dependency failed"); - } - - // Test autowiring deep circular dependencies - unittest { - auto container = new shared DependencyContainer(); - container.register!Ittie; - container.register!Bittie; - container.register!Bunena; - - auto ittie = container.resolve!Ittie; - - assert(ittie.bittie is ittie.bittie.banana.bittie, "Autowiring deep dependencies failed."); - } - - // Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time - unittest { - auto container = new shared DependencyContainer(); - container.register!Ittie.newInstance(); - container.register!Bittie.newInstance(); - container.register!Bunena.newInstance(); - - auto ittie = container.resolve!Ittie; - - assert(ittie.bittie.banana.bittie.banana is null, "Autowiring deep dependencies with newInstance scope autowired a reoccuring type."); - } - - // Test autowiring type registered by interface - unittest { - auto container = new shared DependencyContainer(); - container.register!Bunena; - container.register!Bittie; - container.register!(SuperInterface, SuperImplementation); - - SuperImplementation superInstance = cast(SuperImplementation) container.resolve!SuperInterface; - - assert(!(superInstance.banana is null), "Instance which was resolved by interface type was not autowired."); - } - - // Test reusing a container after clearing all registrations - unittest { - auto container = new shared DependencyContainer(); - container.register!Banana; - container.clearAllRegistrations(); - try { - container.resolve!Banana; - } catch (ResolveException e) { - container.register!Banana; - return; - } - assert(false); - } - - // Test register multiple concrete classess to same interface type - unittest { - auto container = new shared DependencyContainer(); - container.register!(Color, Blue); - container.register!(Color, Red); - } - - // Test removing all registrations for type with multiple registrations. - unittest { - auto container = new shared DependencyContainer(); - container.register!(Color, Blue); - container.register!(Color, Red); - container.removeRegistration!Color; - } - - // Test registering same registration again - unittest { - auto container = new shared DependencyContainer(); - auto firstRegistration = container.register!(Color, Blue); - auto secondRegistration = container.register!(Color, Blue); - - assert(firstRegistration is secondRegistration, "First registration is not the same as the second of equal types"); - } - - // Test resolve registration with multiple qualifiers - unittest { - auto container = new shared DependencyContainer(); - container.register!(Color, Blue); - container.register!(Color, Red); - try { - container.resolve!Color; - } catch (ResolveException e) { - return; - } - assert(false); - } - - // Test resolve registration with multiple qualifiers using a qualifier - unittest { - auto container = new shared DependencyContainer(); - container.register!(Color, Blue); - container.register!(Color, Red); - auto blueInstance = container.resolve!(Color, Blue); - auto redInstance = container.resolve!(Color, Red); - - assert(blueInstance !is redInstance, "Resolving type with multiple, different registrations yielded the same instance"); - assert(blueInstance !is null, "Resolved blue instance to null"); - assert(redInstance !is null, "Resolved red instance to null"); - } - - // Test autowire of unqualified member typed by interface. - unittest { - auto container = new shared DependencyContainer(); - container.register!Spiders; - container.register!(TestInterface, TestClass); - - auto instance = container.resolve!Spiders; - - assert(!(instance is null), "Container failed to autowire member by interface"); - } - - // Register existing registration - unittest { - auto container = new shared DependencyContainer(); - - auto firstRegistration = container.register!TestClass; - auto secondRegistration = container.register!TestClass; - - assert(firstRegistration is secondRegistration, "Registering the same registration twice registers the dependencies twice."); - } - - // Register existing registration by supertype - unittest { - auto container = new shared DependencyContainer(); - - auto firstRegistration = container.register!(TestInterface, TestClass); - auto secondRegistration = container.register!(TestInterface, TestClass); - - assert(firstRegistration is secondRegistration, "Registering the same registration by super type twice registers the dependencies twice."); - } - - // Resolve dependency depending on itself - unittest { - auto container = new shared DependencyContainer(); - container.register!Recursive; - - auto instance = container.resolve!Recursive; - - assert(instance.recursive is instance, "Resolving dependency that depends on itself fails."); - assert(instance.recursive.recursive is instance, "Resolving dependency that depends on itself fails."); - } - - // Test autowire stack pop-back - unittest { - auto container = new shared DependencyContainer(); - container.register!Moolah; - container.register!Wants.newInstance(); - container.register!John; - - container.resolve!Wants; - auto john = container.resolve!John; - - assert(john.wants.moolah !is null, "Autowire stack did not clear entries properly"); - } - - // Test resolving registration registered in different thread - unittest { - auto container = new shared DependencyContainer(); - - auto thread = new Thread(delegate() { - container.register!TestClass; - }); - thread.start(); - thread.join(); - - container.resolve!TestClass; - } - - // Test resolving instance previously resolved in different thread - unittest { - auto container = new shared DependencyContainer(); - shared(TestClass) actualTestClass; - - container.register!TestClass; - - auto thread = new Thread(delegate() { - actualTestClass = cast(shared(TestClass)) container.resolve!TestClass; - }); - thread.start(); - thread.join(); - - shared(TestClass) expectedTestClass = cast(shared(TestClass)) container.resolve!TestClass; - - assert(expectedTestClass is actualTestClass, "Instance resolved in main thread is not the one resolved in thread"); - } - - // Test registering type with option doNotAddConcreteTypeRegistration - unittest { - auto container = new shared DependencyContainer(); - container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration); - - auto firstInstance = container.resolve!TestInterface; - assertThrown!ResolveException(container.resolve!TestClass); - } - - // Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing - unittest { - auto container = new shared DependencyContainer(); - container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration); - container.resolve!TestClass; - } - - // Test registering type will register by contrete type by default - unittest { - auto container = new shared DependencyContainer(); - container.register!(TestInterface, TestClass); - - auto firstInstance = container.resolve!TestInterface; - auto secondInstance = container.resolve!TestClass; - - assert(firstInstance is secondInstance); - } - - // Test resolving all registrations to an interface - unittest { - auto container = new shared DependencyContainer(); - container.register!(Color, Blue); - container.register!(Color, Red); - - auto colors = container.resolveAll!Color; - - assert(colors.length == 2, "resolveAll did not yield all instances of interface type"); - } - - // Test autowiring instances resolved in array - unittest { - auto container = new shared DependencyContainer(); - container.register!UnrelatedClass; - container.register!(TestInterface, TestClassDeux); - - auto instances = container.resolveAll!TestInterface; - auto instance = cast(TestClassDeux) instances[0]; - - assert(instance.unrelated !is null); - } - - // Test set persistent registration options - unittest { - auto container = new shared DependencyContainer(); - container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); - container.register!(TestInterface, TestClass); - assertThrown!ResolveException(container.resolve!TestClass); - } - - // Test unset persistent registration options - unittest { - auto container = new shared DependencyContainer(); - container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); - container.unsetPersistentRegistrationOptions(); - container.register!(TestInterface, TestClass); - container.resolve!TestClass; - } - - // Test registration when resolving - unittest { - auto container = new shared DependencyContainer(); - container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving); - container.resolve!TestClass; - } - - // Test set persistent resolve options - unittest { - auto container = new shared DependencyContainer(); - container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); - container.resolve!TestClass; - } - - // Test unset persistent resolve options - unittest { - auto container = new shared DependencyContainer(); - container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); - container.unsetPersistentResolveOptions(); - assertThrown!ResolveException(container.resolve!TestClass); - } - - // Test ResolveOption registerBeforeResolving fails for interfaces - unittest { - auto container = new shared DependencyContainer(); - assertThrown!ResolveException(container.resolve!TestInterface(ResolveOption.registerBeforeResolving)); - } - - // Test ResolveOption noResolveException does not throw - unittest { - auto container = new shared DependencyContainer(); - auto instance = container.resolve!TestInterface(ResolveOption.noResolveException); - assert(instance is null); - } - - // ResolveOption noResolveException does not throw for resolveAll - unittest { - auto container = new shared DependencyContainer(); - auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException); - assert(instances.length == 0); - } - - // Test autowired, constructor injected class - unittest { - auto container = new shared DependencyContainer(); - container.register!Red; - container.register!Moolah; - container.register!Cocktail; - - auto instance = container.resolve!Cocktail; - - assert(instance !is null); - assert(instance.moolah is container.resolve!Moolah); - assert(instance.red is container.resolve!Red); - } - - // Test injecting constructor with super-type parameter - unittest { - auto container = new shared DependencyContainer(); - container.register!Wallpaper; - container.register!(Color, Blue); - - auto instance = container.resolve!Wallpaper; - assert(instance !is null); - assert(instance.color is container.resolve!Blue); - } - - // Test prevention of circular dependencies during constructor injection - unittest { - auto container = new shared DependencyContainer(); - container.register!Pot; - container.register!Kettle; - - assertThrown!InstanceCreationException(container.resolve!Pot); - } - - // Test prevention of transitive circular dependencies during constructor injection - unittest { - auto container = new shared DependencyContainer(); - container.register!Rock; - container.register!Paper; - container.register!Scissors; - - assertThrown!InstanceCreationException(container.resolve!Rock); - } - - // Test injection of foreign dependency in constructor - unittest { - auto container = new shared DependencyContainer(); - container.register!Ola; - container.register!Hello; - container.resolve!Hello; - } - - // Test PostConstruct method is called after resolving a dependency - unittest { - auto container = new shared DependencyContainer(); - container.register!PostConstructionDependency; - - auto instance = container.resolve!PostConstructionDependency; - assert(instance.postConstructWasCalled == true); - } - - // Test PostConstruct of base type is called - unittest { - auto container = new shared DependencyContainer(); - container.register!ChildOfPostConstruction; - - auto instance = container.resolve!ChildOfPostConstruction; - assert(instance.postConstructWasCalled == true); - } - - // Test PostConstruct of class implementing interface is not called - unittest { - auto container = new shared DependencyContainer(); - container.register!ButThereWontBe; - - auto instance = container.resolve!ButThereWontBe; - assert(instance.postConstructWasCalled == false); - } - - // Test postconstruction happens after autowiring and value injection - unittest { - auto container = new shared DependencyContainer(); - container.register!(ValueInjector!int, PostConstructingIntInjector); - container.register!PostConstructionDependency; - container.register!PostConstructWithAutowiring; - auto instance = container.resolve!PostConstructWithAutowiring; - } - - // Test PreDestroy is called when removing a registration - unittest { - auto container = new shared DependencyContainer(); - container.register!PreDestroyerOfFates; - auto instance = container.resolve!PreDestroyerOfFates; - container.removeRegistration!PreDestroyerOfFates; - assert(instance.preDestroyWasCalled == true); - } - - // Test PreDestroy is called when removing all registrations - unittest { - auto container = new shared DependencyContainer(); - container.register!PreDestroyerOfFates; - auto instance = container.resolve!PreDestroyerOfFates; - container.clearAllRegistrations(); - assert(instance.preDestroyWasCalled == true); - } - - // Test PreDestroy is called when the container is destroyed - unittest { - auto container = new shared DependencyContainer(); - container.register!PreDestroyerOfFates; - auto instance = container.resolve!PreDestroyerOfFates; - container.destroy(); - - assert(instance.preDestroyWasCalled == true); - } + // Test register concrete type + unittest { + auto container = new shared DependencyContainer(); + auto registration = container.register!TestClass; + assert(registration.registeredType == typeid(TestClass), "Type of registered type not the same"); + } + + // Test resolve registered type + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass; + TestClass actualInstance = container.resolve!TestClass; + assert(actualInstance !is null, "Resolved type is null"); + assert(cast(TestClass) actualInstance, "Resolved class is not the same type as expected"); + } + + // Test register interface + unittest { + auto container = new shared DependencyContainer(); + container.register!(TestInterface, TestClass); + TestInterface actualInstance = container.resolve!TestInterface; + assert(actualInstance !is null, "Resolved type is null"); + assert(cast(TestInterface) actualInstance, "Resolved class is not the same type as expected"); + } + + // Test resolve non-registered type + unittest { + auto container = new shared DependencyContainer(); + assertThrown!ResolveException(container.resolve!TestClass, "Resolving non-registered type does not fail"); + } + + // Test clear registrations + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass; + container.clearAllRegistrations(); + assertThrown!ResolveException(container.resolve!TestClass, "Resolving cleared type does not fail"); + } + + // Test resolve single instance for type + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass.singleInstance(); + auto instance1 = container.resolve!TestClass; + auto instance2 = container.resolve!TestClass; + assert(instance1 is instance2, "Resolved instance from single instance scope is not the each time it is resolved"); + } + + // Test resolve new instance for type + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass.newInstance(); + auto instance1 = container.resolve!TestClass; + auto instance2 = container.resolve!TestClass; + assert(instance1 !is instance2, "Resolved instance from new instance scope is the same each time it is resolved"); + } + + // Test resolve existing instance for type + unittest { + auto container = new shared DependencyContainer(); + auto expectedInstance = new TestClass(); + container.register!TestClass.existingInstance(expectedInstance); + auto actualInstance = container.resolve!TestClass; + assert(expectedInstance is actualInstance, "Resolved instance from existing instance scope is not the same as the registered instance"); + } + + // Test autowire resolved instances + unittest { + auto container = new shared DependencyContainer(); + container.register!AutowiredClass; + container.register!ComponentClass; + auto componentInstance = container.resolve!ComponentClass; + auto autowiredInstance = container.resolve!AutowiredClass; + assert(componentInstance.autowiredClass is autowiredInstance, "Member is not autowired upon resolving"); + } + + // Test circular autowiring + unittest { + auto container = new shared DependencyContainer(); + container.register!ComponentMouse; + container.register!ComponentCat; + auto mouse = container.resolve!ComponentMouse; + auto cat = container.resolve!ComponentCat; + assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat, "Circular dependencies should be autowirable"); + } + + // Test remove registration + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass; + container.removeRegistration!TestClass; + assertThrown!ResolveException(container.resolve!TestClass); + } + + // Test autowiring does not autowire member where instance is non-null + unittest { + auto container = new shared DependencyContainer(); + auto existingA = new AutowiredClass(); + auto existingB = new ComponentClass(); + existingB.autowiredClass = existingA; + + container.register!AutowiredClass; + container.register!ComponentClass.existingInstance(existingB); + auto resolvedA = container.resolve!AutowiredClass; + auto resolvedB = container.resolve!ComponentClass; + + assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA, "Autowiring shouldn't rewire member when it is already wired to an instance"); + } + + // Test autowiring circular dependency by third-degree + unittest { + auto container = new shared DependencyContainer(); + container.register!Eenie; + container.register!Meenie; + container.register!Moe; + + auto eenie = container.resolve!Eenie; + + assert(eenie.meenie.moe.eenie is eenie, "Autowiring third-degree circular dependency failed"); + } + + // Test autowiring deep circular dependencies + unittest { + auto container = new shared DependencyContainer(); + container.register!Ittie; + container.register!Bittie; + container.register!Bunena; + + auto ittie = container.resolve!Ittie; + + assert(ittie.bittie is ittie.bittie.banana.bittie, "Autowiring deep dependencies failed."); + } + + // Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time + unittest { + auto container = new shared DependencyContainer(); + container.register!Ittie.newInstance(); + container.register!Bittie.newInstance(); + container.register!Bunena.newInstance(); + + auto ittie = container.resolve!Ittie; + + assert(ittie.bittie.banana.bittie.banana is null, "Autowiring deep dependencies with newInstance scope autowired a reoccuring type."); + } + + // Test autowiring type registered by interface + unittest { + auto container = new shared DependencyContainer(); + container.register!Bunena; + container.register!Bittie; + container.register!(SuperInterface, SuperImplementation); + + SuperImplementation superInstance = cast(SuperImplementation) container.resolve!SuperInterface; + + assert(!(superInstance.banana is null), "Instance which was resolved by interface type was not autowired."); + } + + // Test reusing a container after clearing all registrations + unittest { + auto container = new shared DependencyContainer(); + container.register!Banana; + container.clearAllRegistrations(); + try { + container.resolve!Banana; + } catch (ResolveException e) { + container.register!Banana; + return; + } + assert(false); + } + + // Test register multiple concrete classess to same interface type + unittest { + auto container = new shared DependencyContainer(); + container.register!(Color, Blue); + container.register!(Color, Red); + } + + // Test removing all registrations for type with multiple registrations. + unittest { + auto container = new shared DependencyContainer(); + container.register!(Color, Blue); + container.register!(Color, Red); + container.removeRegistration!Color; + } + + // Test registering same registration again + unittest { + auto container = new shared DependencyContainer(); + auto firstRegistration = container.register!(Color, Blue); + auto secondRegistration = container.register!(Color, Blue); + + assert(firstRegistration is secondRegistration, "First registration is not the same as the second of equal types"); + } + + // Test resolve registration with multiple qualifiers + unittest { + auto container = new shared DependencyContainer(); + container.register!(Color, Blue); + container.register!(Color, Red); + try { + container.resolve!Color; + } catch (ResolveException e) { + return; + } + assert(false); + } + + // Test resolve registration with multiple qualifiers using a qualifier + unittest { + auto container = new shared DependencyContainer(); + container.register!(Color, Blue); + container.register!(Color, Red); + auto blueInstance = container.resolve!(Color, Blue); + auto redInstance = container.resolve!(Color, Red); + + assert(blueInstance !is redInstance, "Resolving type with multiple, different registrations yielded the same instance"); + assert(blueInstance !is null, "Resolved blue instance to null"); + assert(redInstance !is null, "Resolved red instance to null"); + } + + // Test autowire of unqualified member typed by interface. + unittest { + auto container = new shared DependencyContainer(); + container.register!Spiders; + container.register!(TestInterface, TestClass); + + auto instance = container.resolve!Spiders; + + assert(!(instance is null), "Container failed to autowire member by interface"); + } + + // Register existing registration + unittest { + auto container = new shared DependencyContainer(); + + auto firstRegistration = container.register!TestClass; + auto secondRegistration = container.register!TestClass; + + assert(firstRegistration is secondRegistration, "Registering the same registration twice registers the dependencies twice."); + } + + // Register existing registration by supertype + unittest { + auto container = new shared DependencyContainer(); + + auto firstRegistration = container.register!(TestInterface, TestClass); + auto secondRegistration = container.register!(TestInterface, TestClass); + + assert(firstRegistration is secondRegistration, "Registering the same registration by super type twice registers the dependencies twice."); + } + + // Resolve dependency depending on itself + unittest { + auto container = new shared DependencyContainer(); + container.register!Recursive; + + auto instance = container.resolve!Recursive; + + assert(instance.recursive is instance, "Resolving dependency that depends on itself fails."); + assert(instance.recursive.recursive is instance, "Resolving dependency that depends on itself fails."); + } + + // Test autowire stack pop-back + unittest { + auto container = new shared DependencyContainer(); + container.register!Moolah; + container.register!Wants.newInstance(); + container.register!John; + + container.resolve!Wants; + auto john = container.resolve!John; + + assert(john.wants.moolah !is null, "Autowire stack did not clear entries properly"); + } + + // Test resolving registration registered in different thread + unittest { + auto container = new shared DependencyContainer(); + + auto thread = new Thread(delegate() { + container.register!TestClass; + }); + thread.start(); + thread.join(); + + container.resolve!TestClass; + } + + // Test resolving instance previously resolved in different thread + unittest { + auto container = new shared DependencyContainer(); + shared(TestClass) actualTestClass; + + container.register!TestClass; + + auto thread = new Thread(delegate() { + actualTestClass = cast(shared(TestClass)) container.resolve!TestClass; + }); + thread.start(); + thread.join(); + + shared(TestClass) expectedTestClass = cast(shared(TestClass)) container.resolve!TestClass; + + assert(expectedTestClass is actualTestClass, "Instance resolved in main thread is not the one resolved in thread"); + } + + // Test registering type with option doNotAddConcreteTypeRegistration + unittest { + auto container = new shared DependencyContainer(); + container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration); + + auto firstInstance = container.resolve!TestInterface; + assertThrown!ResolveException(container.resolve!TestClass); + } + + // Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing + unittest { + auto container = new shared DependencyContainer(); + container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration); + container.resolve!TestClass; + } + + // Test registering type will register by contrete type by default + unittest { + auto container = new shared DependencyContainer(); + container.register!(TestInterface, TestClass); + + auto firstInstance = container.resolve!TestInterface; + auto secondInstance = container.resolve!TestClass; + + assert(firstInstance is secondInstance); + } + + // Test resolving all registrations to an interface + unittest { + auto container = new shared DependencyContainer(); + container.register!(Color, Blue); + container.register!(Color, Red); + + auto colors = container.resolveAll!Color; + + assert(colors.length == 2, "resolveAll did not yield all instances of interface type"); + } + + // Test autowiring instances resolved in array + unittest { + auto container = new shared DependencyContainer(); + container.register!UnrelatedClass; + container.register!(TestInterface, TestClassDeux); + + auto instances = container.resolveAll!TestInterface; + auto instance = cast(TestClassDeux) instances[0]; + + assert(instance.unrelated !is null); + } + + // Test set persistent registration options + unittest { + auto container = new shared DependencyContainer(); + container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); + container.register!(TestInterface, TestClass); + assertThrown!ResolveException(container.resolve!TestClass); + } + + // Test unset persistent registration options + unittest { + auto container = new shared DependencyContainer(); + container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); + container.unsetPersistentRegistrationOptions(); + container.register!(TestInterface, TestClass); + container.resolve!TestClass; + } + + // Test registration when resolving + unittest { + auto container = new shared DependencyContainer(); + container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving); + container.resolve!TestClass; + } + + // Test set persistent resolve options + unittest { + auto container = new shared DependencyContainer(); + container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); + container.resolve!TestClass; + } + + // Test unset persistent resolve options + unittest { + auto container = new shared DependencyContainer(); + container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); + container.unsetPersistentResolveOptions(); + assertThrown!ResolveException(container.resolve!TestClass); + } + + // Test ResolveOption registerBeforeResolving fails for interfaces + unittest { + auto container = new shared DependencyContainer(); + assertThrown!ResolveException(container.resolve!TestInterface(ResolveOption.registerBeforeResolving)); + } + + // Test ResolveOption noResolveException does not throw + unittest { + auto container = new shared DependencyContainer(); + auto instance = container.resolve!TestInterface(ResolveOption.noResolveException); + assert(instance is null); + } + + // ResolveOption noResolveException does not throw for resolveAll + unittest { + auto container = new shared DependencyContainer(); + auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException); + assert(instances.length == 0); + } + + // Test autowired, constructor injected class + unittest { + auto container = new shared DependencyContainer(); + container.register!Red; + container.register!Moolah; + container.register!Cocktail; + + auto instance = container.resolve!Cocktail; + + assert(instance !is null); + assert(instance.moolah is container.resolve!Moolah); + assert(instance.red is container.resolve!Red); + } + + // Test injecting constructor with super-type parameter + unittest { + auto container = new shared DependencyContainer(); + container.register!Wallpaper; + container.register!(Color, Blue); + + auto instance = container.resolve!Wallpaper; + assert(instance !is null); + assert(instance.color is container.resolve!Blue); + } + + // Test prevention of circular dependencies during constructor injection + unittest { + auto container = new shared DependencyContainer(); + container.register!Pot; + container.register!Kettle; + + assertThrown!InstanceCreationException(container.resolve!Pot); + } + + // Test prevention of transitive circular dependencies during constructor injection + unittest { + auto container = new shared DependencyContainer(); + container.register!Rock; + container.register!Paper; + container.register!Scissors; + + assertThrown!InstanceCreationException(container.resolve!Rock); + } + + // Test injection of foreign dependency in constructor + unittest { + auto container = new shared DependencyContainer(); + container.register!Ola; + container.register!Hello; + container.resolve!Hello; + } + + // Test PostConstruct method is called after resolving a dependency + unittest { + auto container = new shared DependencyContainer(); + container.register!PostConstructionDependency; + + auto instance = container.resolve!PostConstructionDependency; + assert(instance.postConstructWasCalled == true); + } + + // Test PostConstruct of base type is called + unittest { + auto container = new shared DependencyContainer(); + container.register!ChildOfPostConstruction; + + auto instance = container.resolve!ChildOfPostConstruction; + assert(instance.postConstructWasCalled == true); + } + + // Test PostConstruct of class implementing interface is not called + unittest { + auto container = new shared DependencyContainer(); + container.register!ButThereWontBe; + + auto instance = container.resolve!ButThereWontBe; + assert(instance.postConstructWasCalled == false); + } + + // Test postconstruction happens after autowiring and value injection + unittest { + auto container = new shared DependencyContainer(); + container.register!(ValueInjector!int, PostConstructingIntInjector); + container.register!PostConstructionDependency; + container.register!PostConstructWithAutowiring; + auto instance = container.resolve!PostConstructWithAutowiring; + } + + // Test PreDestroy is called when removing a registration + unittest { + auto container = new shared DependencyContainer(); + container.register!PreDestroyerOfFates; + auto instance = container.resolve!PreDestroyerOfFates; + container.removeRegistration!PreDestroyerOfFates; + assert(instance.preDestroyWasCalled == true); + } + + // Test PreDestroy is called when removing all registrations + unittest { + auto container = new shared DependencyContainer(); + container.register!PreDestroyerOfFates; + auto instance = container.resolve!PreDestroyerOfFates; + container.clearAllRegistrations(); + assert(instance.preDestroyWasCalled == true); + } + + // Test PreDestroy is called when the container is destroyed + unittest { + auto container = new shared DependencyContainer(); + container.register!PreDestroyerOfFates; + auto instance = container.resolve!PreDestroyerOfFates; + container.destroy(); + + assert(instance.preDestroyWasCalled == true); + } } diff --git a/test/poodinis/contexttest.d b/test/poodinis/contexttest.d index 5e4fe5e..9bb41af 100644 --- a/test/poodinis/contexttest.d +++ b/test/poodinis/contexttest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -12,105 +12,105 @@ import std.exception; version(unittest) { - //Test register component registrations from context - unittest { - auto container = new shared DependencyContainer(); - auto context = new TestContext(); - context.registerContextComponents(container); - auto bananaInstance = container.resolve!Banana; + //Test register component registrations from context + unittest { + auto container = new shared DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); + auto bananaInstance = container.resolve!Banana; - assert(bananaInstance.color == "Yellow"); - } + assert(bananaInstance.color == "Yellow"); + } - //Test non-annotated methods are not registered - unittest { - auto container = new shared DependencyContainer(); - auto context = new TestContext(); - context.registerContextComponents(container); - assertThrown!ResolveException(container.resolve!Apple); - } + //Test non-annotated methods are not registered + unittest { + auto container = new shared DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); + assertThrown!ResolveException(container.resolve!Apple); + } - //Test register component by base type - unittest { - auto container = new shared DependencyContainer(); - auto context = new TestContext(); - context.registerContextComponents(container); - auto instance = container.resolve!Fruit; - assert(instance.getShape() == "Pear shaped"); - } + //Test register component by base type + unittest { + auto container = new shared DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); + auto instance = container.resolve!Fruit; + assert(instance.getShape() == "Pear shaped"); + } - //Test register components with multiple candidates - unittest { - auto container = new shared DependencyContainer(); - auto context = new TestContext(); - context.registerContextComponents(container); + //Test register components with multiple candidates + unittest { + auto container = new shared DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); - auto rabbit = container.resolve!(Animal, Rabbit); - assert(rabbit.getYell() == "Squeeeeeel"); + auto rabbit = container.resolve!(Animal, Rabbit); + assert(rabbit.getYell() == "Squeeeeeel"); - auto wolf = container.resolve!(Animal, Wolf); - assert(wolf.getYell() == "Wooooooooooo"); - } + auto wolf = container.resolve!(Animal, Wolf); + assert(wolf.getYell() == "Wooooooooooo"); + } - //Test register component as prototype - unittest { - auto container = new shared DependencyContainer(); - auto context = new TestContext(); - context.registerContextComponents(container); + //Test register component as prototype + unittest { + auto container = new shared DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); - auto firstInstance = container.resolve!PieChart; - auto secondInstance = container.resolve!PieChart; + auto firstInstance = container.resolve!PieChart; + auto secondInstance = container.resolve!PieChart; - assert(firstInstance !is null && secondInstance !is null); - assert(firstInstance !is secondInstance); - } + assert(firstInstance !is null && secondInstance !is null); + assert(firstInstance !is secondInstance); + } - // Test setting up simple dependencies through application context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!SimpleContext; - auto instance = container.resolve!CakeChart; + // Test setting up simple dependencies through application context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!SimpleContext; + auto instance = container.resolve!CakeChart; - assert(instance !is null); - } + assert(instance !is null); + } - // Test resolving dependency from registered application context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!SimpleContext; - auto instance = container.resolve!Apple; + // Test resolving dependency from registered application context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!SimpleContext; + auto instance = container.resolve!Apple; - assert(instance !is null); - } + assert(instance !is null); + } - // Test autowiring application context - unittest { - auto container = new shared DependencyContainer(); - container.register!Apple; - container.registerContext!AutowiredTestContext; - auto instance = container.resolve!ClassWrapper; + // Test autowiring application context + unittest { + auto container = new shared DependencyContainer(); + container.register!Apple; + container.registerContext!AutowiredTestContext; + auto instance = container.resolve!ClassWrapper; - assert(instance !is null); - assert(instance.someClass !is null); - } + assert(instance !is null); + assert(instance.someClass !is null); + } - // Test autowiring application context with dependencies registered in same context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!ComplexAutowiredTestContext; - auto instance = container.resolve!ClassWrapperWrapper; - auto wrapper = container.resolve!ClassWrapper; - auto someClass = container.resolve!Apple; + // Test autowiring application context with dependencies registered in same context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!ComplexAutowiredTestContext; + auto instance = container.resolve!ClassWrapperWrapper; + auto wrapper = container.resolve!ClassWrapper; + auto someClass = container.resolve!Apple; - assert(instance !is null); - assert(instance.wrapper is wrapper); - assert(instance.wrapper.someClass is someClass); - } + assert(instance !is null); + assert(instance.wrapper is wrapper); + assert(instance.wrapper.someClass is someClass); + } - // Test resolving registered context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!TestContext; - container.resolve!ApplicationContext; - } + // Test resolving registered context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!TestContext; + container.resolve!ApplicationContext; + } } diff --git a/test/poodinis/factorytest.d b/test/poodinis/factorytest.d index e19537f..419eb46 100644 --- a/test/poodinis/factorytest.d +++ b/test/poodinis/factorytest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -12,137 +12,137 @@ import std.exception; version(unittest) { - // Test instance factory with singletons - unittest { - auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes); - auto instanceOne = factory.getInstance(); - auto instanceTwo = factory.getInstance(); + // Test instance factory with singletons + unittest { + auto factory = new InstanceFactory(); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes); + auto instanceOne = factory.getInstance(); + auto instanceTwo = factory.getInstance(); - assert(instanceOne !is null, "Created factory instance is null"); - assert(instanceOne is instanceTwo, "Created factory instance is not the same"); - } + assert(instanceOne !is null, "Created factory instance is null"); + assert(instanceOne is instanceTwo, "Created factory instance is not the same"); + } - // Test instance factory with new instances - unittest { - auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no); - auto instanceOne = factory.getInstance(); - auto instanceTwo = factory.getInstance(); + // Test instance factory with new instances + unittest { + auto factory = new InstanceFactory(); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no); + auto instanceOne = factory.getInstance(); + auto instanceTwo = factory.getInstance(); - assert(instanceOne !is null, "Created factory instance is null"); - assert(instanceOne !is instanceTwo, "Created factory instance is the same"); - } + assert(instanceOne !is null, "Created factory instance is null"); + assert(instanceOne !is instanceTwo, "Created factory instance is the same"); + } - // Test instance factory with existing instances - unittest { - auto existingInstance = new TestImplementation(); - auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes, existingInstance); - auto instanceOne = factory.getInstance(); - auto instanceTwo = factory.getInstance(); + // Test instance factory with existing instances + unittest { + auto existingInstance = new TestImplementation(); + auto factory = new InstanceFactory(); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes, existingInstance); + auto instanceOne = factory.getInstance(); + auto instanceTwo = factory.getInstance(); - assert(instanceOne is existingInstance, "Created factory instance is not the existing instance"); - assert(instanceTwo is existingInstance, "Created factory instance is not the existing instance when called again"); - } + assert(instanceOne is existingInstance, "Created factory instance is not the existing instance"); + assert(instanceTwo is existingInstance, "Created factory instance is not the existing instance when called again"); + } - // Test instance factory with existing instances when setting singleton flag to "no" - unittest { - auto existingInstance = new TestImplementation(); - auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no, existingInstance); - auto instance = factory.getInstance(); + // Test instance factory with existing instances when setting singleton flag to "no" + unittest { + auto existingInstance = new TestImplementation(); + auto factory = new InstanceFactory(); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no, existingInstance); + auto instance = factory.getInstance(); - assert(instance is existingInstance, "Created factory instance is not the existing instance"); - } + assert(instance is existingInstance, "Created factory instance is not the existing instance"); + } - // Test creating instance using custom factory method - unittest { - Object factoryMethod() { - auto instance = new TestImplementation(); - instance.someContent = "Ducks!"; - return instance; - } + // Test creating instance using custom factory method + unittest { + Object factoryMethod() { + auto instance = new TestImplementation(); + instance.someContent = "Ducks!"; + return instance; + } - auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(null, CreatesSingleton.yes, null, &factoryMethod); - auto instance = cast(TestImplementation) factory.getInstance(); + auto factory = new InstanceFactory(); + factory.factoryParameters = InstanceFactoryParameters(null, CreatesSingleton.yes, null, &factoryMethod); + auto instance = cast(TestImplementation) factory.getInstance(); - assert(instance !is null, "No instance was created by factory or could not be cast to expected type"); - assert(instance.someContent == "Ducks!"); - } + assert(instance !is null, "No instance was created by factory or could not be cast to expected type"); + assert(instance.someContent == "Ducks!"); + } - // Test injecting constructor of class - unittest { - auto container = new shared DependencyContainer(); - container.register!TestImplementation; + // Test injecting constructor of class + unittest { + auto container = new shared DependencyContainer(); + container.register!TestImplementation; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructor(container); - auto instance = cast(ClassWithConstructor) factory.getInstance(); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructor(container); + auto instance = cast(ClassWithConstructor) factory.getInstance(); - assert(instance !is null); - assert(instance.testImplementation is container.resolve!TestImplementation); - } + assert(instance !is null); + assert(instance.testImplementation is container.resolve!TestImplementation); + } - // Test injecting constructor of class with multiple constructors injects the first candidate - unittest { - auto container = new shared DependencyContainer(); - container.register!SomeOtherClassThen; - container.register!TestImplementation; + // Test injecting constructor of class with multiple constructors injects the first candidate + unittest { + auto container = new shared DependencyContainer(); + container.register!SomeOtherClassThen; + container.register!TestImplementation; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(container); - auto instance = cast(ClassWithMultipleConstructors) factory.getInstance(); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(container); + auto instance = cast(ClassWithMultipleConstructors) factory.getInstance(); - assert(instance !is null); - assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); - assert(instance.testImplementation is null); - } + assert(instance !is null); + assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); + assert(instance.testImplementation is null); + } - // Test injecting constructor of class with multiple constructor parameters - unittest { - auto container = new shared DependencyContainer(); - container.register!SomeOtherClassThen; - container.register!TestImplementation; + // Test injecting constructor of class with multiple constructor parameters + unittest { + auto container = new shared DependencyContainer(); + container.register!SomeOtherClassThen; + container.register!TestImplementation; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(container); - auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance(); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(container); + auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance(); - assert(instance !is null); - assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); - assert(instance.testImplementation is container.resolve!TestImplementation); - } + assert(instance !is null); + assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); + assert(instance.testImplementation is container.resolve!TestImplementation); + } - // Test injecting constructor of class with primitive constructor parameters - unittest { - auto container = new shared DependencyContainer(); - container.register!SomeOtherClassThen; + // Test injecting constructor of class with primitive constructor parameters + unittest { + auto container = new shared DependencyContainer(); + container.register!SomeOtherClassThen; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(container); - auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance(); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(container); + auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance(); - assert(instance !is null); - assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); - } + assert(instance !is null); + assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen); + } - // Test injecting constructor of class with empty constructor will skip injection - unittest { - auto container = new shared DependencyContainer(); + // Test injecting constructor of class with empty constructor will skip injection + unittest { + auto container = new shared DependencyContainer(); - auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container); - auto instance = cast(ClassWithEmptyConstructor) factory.getInstance(); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container); + auto instance = cast(ClassWithEmptyConstructor) factory.getInstance(); - assert(instance !is null); - assert(instance.someOtherClassThen is null); - } + assert(instance !is null); + assert(instance.someOtherClassThen is null); + } - // Test injecting constructor of class with no candidates fails - unittest { - auto container = new shared DependencyContainer(); + // Test injecting constructor of class with no candidates fails + unittest { + auto container = new shared DependencyContainer(); - auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(container); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(container); - assertThrown!InstanceCreationException(factory.getInstance()); - } + assertThrown!InstanceCreationException(factory.getInstance()); + } } diff --git a/test/poodinis/foreigndependencies.d b/test/poodinis/foreigndependencies.d index 25590f8..354bb03 100644 --- a/test/poodinis/foreigndependencies.d +++ b/test/poodinis/foreigndependencies.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -8,5 +8,5 @@ module poodinis.test.foreignDependencies; version(unittest) { - class Ola {} + class Ola {} } diff --git a/test/poodinis/registrationtest.d b/test/poodinis/registrationtest.d index d5be162..3280a61 100644 --- a/test/poodinis/registrationtest.d +++ b/test/poodinis/registrationtest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -12,51 +12,51 @@ import std.exception; version(unittest) { - // Test getting instance without scope defined throws exception - unittest { - Registration registration = new Registration(typeid(TestType), null, null, null); - assertThrown!(InstanceCreationException)(registration.getInstance(), null); - } + // Test getting instance without scope defined throws exception + unittest { + Registration registration = new Registration(typeid(TestType), null, null, null); + assertThrown!(InstanceCreationException)(registration.getInstance(), null); + } - // Test set single instance scope using scope setter - unittest { - Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); - auto chainedRegistration = registration.singleInstance(); - auto instance1 = registration.getInstance(); - auto instance2 = registration.getInstance(); - assert(instance1 is instance2, "Registration with single instance scope did not return the same instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); - } + // Test set single instance scope using scope setter + unittest { + Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); + auto chainedRegistration = registration.singleInstance(); + auto instance1 = registration.getInstance(); + auto instance2 = registration.getInstance(); + assert(instance1 is instance2, "Registration with single instance scope did not return the same instance"); + assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + } - // Test set new instance scope using scope setter - unittest { - Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); - auto chainedRegistration = registration.newInstance(); - auto instance1 = registration.getInstance(); - auto instance2 = registration.getInstance(); - assert(instance1 !is instance2, "Registration with new instance scope did not return a different instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); - } + // Test set new instance scope using scope setter + unittest { + Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); + auto chainedRegistration = registration.newInstance(); + auto instance1 = registration.getInstance(); + auto instance2 = registration.getInstance(); + assert(instance1 !is instance2, "Registration with new instance scope did not return a different instance"); + assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + } - // Test set existing instance scope using scope setter - unittest { - Registration registration = new Registration(null, null, new InstanceFactory(), null); - auto expectedInstance = new TestType(); - auto chainedRegistration = registration.existingInstance(expectedInstance); - auto actualInstance = registration.getInstance(); - assert(expectedInstance is expectedInstance, "Registration with existing instance scope did not return the same instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); - } + // Test set existing instance scope using scope setter + unittest { + Registration registration = new Registration(null, null, new InstanceFactory(), null); + auto expectedInstance = new TestType(); + auto chainedRegistration = registration.existingInstance(expectedInstance); + auto actualInstance = registration.getInstance(); + assert(expectedInstance is expectedInstance, "Registration with existing instance scope did not return the same instance"); + assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + } - // Test linking registrations - unittest { - Registration firstRegistration = new Registration(typeid(TestInterface), typeid(TestImplementation), new InstanceFactory(), null).singleInstance(); - Registration secondRegistration = new Registration(typeid(TestImplementation), typeid(TestImplementation), new InstanceFactory(), null).singleInstance().linkTo(firstRegistration); + // Test linking registrations + unittest { + Registration firstRegistration = new Registration(typeid(TestInterface), typeid(TestImplementation), new InstanceFactory(), null).singleInstance(); + Registration secondRegistration = new Registration(typeid(TestImplementation), typeid(TestImplementation), new InstanceFactory(), null).singleInstance().linkTo(firstRegistration); - auto firstInstance = firstRegistration.getInstance(); - auto secondInstance = secondRegistration.getInstance(); + auto firstInstance = firstRegistration.getInstance(); + auto secondInstance = secondRegistration.getInstance(); - assert(firstInstance is secondInstance); - } + assert(firstInstance is secondInstance); + } } diff --git a/test/poodinis/testclasses.d b/test/poodinis/testclasses.d index 9dcf864..10956e6 100644 --- a/test/poodinis/testclasses.d +++ b/test/poodinis/testclasses.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -11,623 +11,623 @@ import poodinis; import poodinis.test.foreignDependencies; version(unittest) { - class ComponentA {} + class ComponentA {} - class ComponentB { - public @Autowire ComponentA componentA; - } + class ComponentB { + public @Autowire ComponentA componentA; + } - interface InterfaceA {} + interface InterfaceA {} - class ComponentC : InterfaceA {} + class ComponentC : InterfaceA {} - class ComponentD { - public @Autowire InterfaceA componentC = null; - private @Autowire InterfaceA _privateComponentC = null; + class ComponentD { + public @Autowire InterfaceA componentC = null; + private @Autowire InterfaceA _privateComponentC = null; - public InterfaceA privateComponentC() { - return _privateComponentC; - } - } + public InterfaceA privateComponentC() { + return _privateComponentC; + } + } - class DummyAttribute{}; + class DummyAttribute{}; - class ComponentE { - @DummyAttribute - public ComponentC componentC; - } + class ComponentE { + @DummyAttribute + public ComponentC componentC; + } - class ComponentDeclarationCocktail { - alias noomer = int; + class ComponentDeclarationCocktail { + alias noomer = int; - @Autowire - public ComponentA componentA; - - public void doesNothing() { - } + @Autowire + public ComponentA componentA; + + public void doesNothing() { + } - ~this(){ - } - } + ~this(){ + } + } - class ComponentX : InterfaceA {} - - class ComponentZ : ComponentB { - } - - class MonkeyShine { - @Autowire!ComponentX - public InterfaceA component; - } - - class BootstrapBootstrap { - @Autowire!ComponentX - public InterfaceA componentX; - - @Autowire!ComponentC - public InterfaceA componentC; - } - - class LordOfTheComponents { - @Autowire - public InterfaceA[] components; - } - class ComponentCharlie { - @Autowire - @AssignNewInstance - public ComponentA componentA; - } - - class OuttaTime { - @Autowire - @OptionalDependency - public InterfaceA interfaceA; - - @Autowire - @OptionalDependency - public ComponentA componentA; - - @Autowire - @OptionalDependency - public ComponentC[] componentCs; - } - - class ValuedClass { - @Value("values.int") - public int intValue; - - @Autowire - public ComponentA unrelated; - } - - class TestInjector : ValueInjector!int { - public override int get(string key) { - assert(key == "values.int"); - return 8; - } - } - - interface TestInterface {} - - class TestClass : TestInterface { - } - - class TestClassDeux : TestInterface { - @Autowire - public UnrelatedClass unrelated; - } - - class UnrelatedClass{ - } - - class FailOnCreationClass { - this() { - throw new Exception("This class should not be instantiated"); - } - } - - class AutowiredClass { - } - - class ComponentClass { - @Autowire - public AutowiredClass autowiredClass; - } - - class ComponentCat { - @Autowire - public ComponentMouse mouse; - } - - class ComponentMouse { - @Autowire - public ComponentCat cat; - } - - class Eenie { - @Autowire - public Meenie meenie; - } - - class Meenie { - @Autowire - public Moe moe; - } - - class Moe { - @Autowire - public Eenie eenie; - } - - class Ittie { - @Autowire - public Bittie bittie; - } - - class Bittie { - @Autowire - public Bunena banana; - } - - class Bunena { - @Autowire - public Bittie bittie; - } - - interface SuperInterface { - } - - class SuperImplementation : SuperInterface { - @Autowire - public Bunena banana; - } - - interface Color { - } - - class Blue : Color { - } - - class Red : Color { - } - - class Spiders { - @Autowire - public TestInterface testMember; - } - - class Recursive { - @Autowire - public Recursive recursive; - } - - class Moolah {} - - class Wants { - @Autowire - public Moolah moolah; - } - - class John { - @Autowire - public Wants wants; - } - - class Cocktail { - @Autowire - public Moolah moolah; - - public Red red; - - this(Red red) { - this.red = red; - } - } - - class Wallpaper { - public Color color; - - this(Color color) { - this.color = color; - } - } - - class Pot { - this(Kettle kettle) {} - } - - class Kettle { - this(Pot pot) {} - } - - class Rock { - this(Scissors scissors) {} - } - - class Paper { - this(Rock rock) {} - } - - class Scissors { - this(Paper paper) {} - } - - class Hello { - this(Ola ola) {} - } - - class PostConstructionDependency { - public bool postConstructWasCalled = false; - - @PostConstruct - public void callMeMaybe() { - postConstructWasCalled = true; - } - } - - class ChildOfPostConstruction : PostConstructionDependency {} - - interface ThereWillBePostConstruction { - @PostConstruct - void constructIt(); - } - - class ButThereWontBe : ThereWillBePostConstruction { - public bool postConstructWasCalled = false; - - public override void constructIt() { - postConstructWasCalled = true; - } - } - - class PostConstructWithAutowiring { - @Autowire - private PostConstructionDependency dependency; + class ComponentX : InterfaceA {} + + class ComponentZ : ComponentB { + } + + class MonkeyShine { + @Autowire!ComponentX + public InterfaceA component; + } + + class BootstrapBootstrap { + @Autowire!ComponentX + public InterfaceA componentX; + + @Autowire!ComponentC + public InterfaceA componentC; + } + + class LordOfTheComponents { + @Autowire + public InterfaceA[] components; + } + class ComponentCharlie { + @Autowire + @AssignNewInstance + public ComponentA componentA; + } + + class OuttaTime { + @Autowire + @OptionalDependency + public InterfaceA interfaceA; + + @Autowire + @OptionalDependency + public ComponentA componentA; + + @Autowire + @OptionalDependency + public ComponentC[] componentCs; + } + + class ValuedClass { + @Value("values.int") + public int intValue; + + @Autowire + public ComponentA unrelated; + } + + class TestInjector : ValueInjector!int { + public override int get(string key) { + assert(key == "values.int"); + return 8; + } + } + + interface TestInterface {} + + class TestClass : TestInterface { + } + + class TestClassDeux : TestInterface { + @Autowire + public UnrelatedClass unrelated; + } + + class UnrelatedClass{ + } + + class FailOnCreationClass { + this() { + throw new Exception("This class should not be instantiated"); + } + } + + class AutowiredClass { + } + + class ComponentClass { + @Autowire + public AutowiredClass autowiredClass; + } + + class ComponentCat { + @Autowire + public ComponentMouse mouse; + } + + class ComponentMouse { + @Autowire + public ComponentCat cat; + } + + class Eenie { + @Autowire + public Meenie meenie; + } + + class Meenie { + @Autowire + public Moe moe; + } + + class Moe { + @Autowire + public Eenie eenie; + } + + class Ittie { + @Autowire + public Bittie bittie; + } + + class Bittie { + @Autowire + public Bunena banana; + } + + class Bunena { + @Autowire + public Bittie bittie; + } + + interface SuperInterface { + } + + class SuperImplementation : SuperInterface { + @Autowire + public Bunena banana; + } + + interface Color { + } + + class Blue : Color { + } + + class Red : Color { + } + + class Spiders { + @Autowire + public TestInterface testMember; + } + + class Recursive { + @Autowire + public Recursive recursive; + } + + class Moolah {} + + class Wants { + @Autowire + public Moolah moolah; + } + + class John { + @Autowire + public Wants wants; + } + + class Cocktail { + @Autowire + public Moolah moolah; + + public Red red; + + this(Red red) { + this.red = red; + } + } + + class Wallpaper { + public Color color; + + this(Color color) { + this.color = color; + } + } + + class Pot { + this(Kettle kettle) {} + } + + class Kettle { + this(Pot pot) {} + } + + class Rock { + this(Scissors scissors) {} + } + + class Paper { + this(Rock rock) {} + } + + class Scissors { + this(Paper paper) {} + } + + class Hello { + this(Ola ola) {} + } + + class PostConstructionDependency { + public bool postConstructWasCalled = false; + + @PostConstruct + public void callMeMaybe() { + postConstructWasCalled = true; + } + } + + class ChildOfPostConstruction : PostConstructionDependency {} + + interface ThereWillBePostConstruction { + @PostConstruct + void constructIt(); + } + + class ButThereWontBe : ThereWillBePostConstruction { + public bool postConstructWasCalled = false; + + public override void constructIt() { + postConstructWasCalled = true; + } + } + + class PostConstructWithAutowiring { + @Autowire + private PostConstructionDependency dependency; - @Value("") - private int theNumber = 1; - - @PostConstruct - public void doIt() { - assert(theNumber == 8783); - assert(dependency !is null); - } - } - - class PreDestroyerOfFates { - public bool preDestroyWasCalled = false; - - @PreDestroy - public void callMeMaybe() { - preDestroyWasCalled = true; - } - } + @Value("") + private int theNumber = 1; + + @PostConstruct + public void doIt() { + assert(theNumber == 8783); + assert(dependency !is null); + } + } + + class PreDestroyerOfFates { + public bool preDestroyWasCalled = false; + + @PreDestroy + public void callMeMaybe() { + preDestroyWasCalled = true; + } + } - class PostConstructingIntInjector : ValueInjector!int { - int get(string key) { - return 8783; - } - } - - interface Fruit { - string getShape(); - } + class PostConstructingIntInjector : ValueInjector!int { + int get(string key) { + return 8783; + } + } + + interface Fruit { + string getShape(); + } - interface Animal { - string getYell(); - } + interface Animal { + string getYell(); + } - class Banana { - public string color; - - this(string color) { - this.color = color; - } - } - - class Apple {} - - class Pear : Fruit { - public override string getShape() { - return "Pear shaped"; - } - } - - class Rabbit : Animal { - public override string getYell() { - return "Squeeeeeel"; - } - } - - class Wolf : Animal { - public override string getYell() { - return "Wooooooooooo"; - } - } - - class PieChart {} - - class CakeChart : PieChart {} - - class ClassWrapper { - public Object someClass; - - this(Object someClass) { - this.someClass = someClass; - } - } - - class ClassWrapperWrapper { - public ClassWrapper wrapper; - - this(ClassWrapper wrapper) { - this.wrapper = wrapper; - } - } - - class SimpleContext : ApplicationContext { - public override void registerDependencies(shared(DependencyContainer) container) { - container.register!CakeChart; - } - - @Component - public Apple apple() { - return new Apple(); - } - } - - class ComplexAutowiredTestContext : ApplicationContext { - - @Autowire - private Apple apple; - - @Autowire - protected ClassWrapper classWrapper; - - public override void registerDependencies(shared(DependencyContainer) container) { - container.register!Apple; - } - - @Component - public ClassWrapper wrapper() { - return new ClassWrapper(apple); - } - - @Component - public ClassWrapperWrapper wrapperWrapper() { - return new ClassWrapperWrapper(classWrapper); - } - - } - - class AutowiredTestContext : ApplicationContext { - - @Autowire - private Apple apple; - - @Component - public ClassWrapper wrapper() { - return new ClassWrapper(apple); - } - } - - class TestContext : ApplicationContext { - - @Component - public Banana banana() { - return new Banana("Yellow"); - } - - public Apple apple() { - return new Apple(); - } - - @Component - @RegisterByType!Fruit - public Pear pear() { - return new Pear(); - } - - @Component - @RegisterByType!Animal - public Rabbit rabbit() { - return new Rabbit(); - } - - @Component - @RegisterByType!Animal - public Wolf wolf() { - return new Wolf(); - } - - @Component - @Prototype - public PieChart pieChart() { - return new PieChart(); - } - } - - class TestImplementation : TestInterface { - public string someContent = ""; - } - - class SomeOtherClassThen { - } - - class ClassWithConstructor { - public TestImplementation testImplementation; - - this(TestImplementation testImplementation) { - this.testImplementation = testImplementation; - } - } - - class ClassWithMultipleConstructors { - public SomeOtherClassThen someOtherClassThen; - public TestImplementation testImplementation; - - this(SomeOtherClassThen someOtherClassThen) { - this.someOtherClassThen = someOtherClassThen; - } - - this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { - this.someOtherClassThen = someOtherClassThen; - this.testImplementation = testImplementation; - } - } - - class ClassWithConstructorWithMultipleParameters { - public SomeOtherClassThen someOtherClassThen; - public TestImplementation testImplementation; - - this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { - this.someOtherClassThen = someOtherClassThen; - this.testImplementation = testImplementation; - } - } - - class ClassWithPrimitiveConstructor { - public SomeOtherClassThen someOtherClassThen; - - this(string willNotBePicked) { - } - - this(SomeOtherClassThen someOtherClassThen) { - this.someOtherClassThen = someOtherClassThen; - } - } - - class ClassWithEmptyConstructor { - public SomeOtherClassThen someOtherClassThen; - - this() { - } - - this(SomeOtherClassThen someOtherClassThen) { - this.someOtherClassThen = someOtherClassThen; - } - } - - class ClassWithNonInjectableConstructor { - this(string myName) { - } - } - - class TestType {} - - class Dependency {} - - struct Thing { - int x; - } - - class MyConfig { - @Value("conf.stuffs") - int stuffs; - - @Value("conf.name") - string name; - - @Value("conf.thing") - Thing thing; - } - - class ConfigWithDefaults { - @Value("conf.missing") - int noms = 9; - } - - class ConfigWithMandatory { - @MandatoryValue("conf.mustbethere") - int nums; - } - - class IntInjector : ValueInjector!int { - public override int get(string key) { - assert(key == "conf.stuffs"); - return 364; - } - } - - class StringInjector : ValueInjector!string { - public override string get(string key) { - assert(key == "conf.name"); - return "Le Chef"; - } - } - - class ThingInjector : ValueInjector!Thing { - public override Thing get(string key) { - assert(key == "conf.thing"); - return Thing(8899); - } - } - - class DefaultIntInjector : ValueInjector!int { - public override int get(string key) { - throw new ValueNotAvailableException(key); - } - } - - class MandatoryAvailableIntInjector : ValueInjector!int { - public override int get(string key) { - return 7466; - } - } - - class MandatoryUnavailableIntInjector : ValueInjector!int { - public override int get(string key) { - throw new ValueNotAvailableException(key); - } - } - - class DependencyInjectedIntInjector : ValueInjector!int { - @Autowire - public Dependency dependency; - - public override int get(string key) { - return 2345; - } - } - - class CircularIntInjector : ValueInjector!int { - @Autowire - public ValueInjector!int dependency; - - private int count = 0; - - public override int get(string key) { - count += 1; - if (count >= 3) { - return count; - } - return dependency.get(key); - } - } - - class ValueInjectedIntInjector : ValueInjector!int { - @Value("five") - public int count = 0; - - public override int get(string key) { - if (key == "five") { - return 5; - } - - return count; - } - } - - class DependencyValueInjectedIntInjector : ValueInjector!int { - @Autowire - public ConfigWithDefaults config; - - public override int get(string key) { - if (key == "conf.missing") { - return 8899; - } - - return 0; - } - } + class Banana { + public string color; + + this(string color) { + this.color = color; + } + } + + class Apple {} + + class Pear : Fruit { + public override string getShape() { + return "Pear shaped"; + } + } + + class Rabbit : Animal { + public override string getYell() { + return "Squeeeeeel"; + } + } + + class Wolf : Animal { + public override string getYell() { + return "Wooooooooooo"; + } + } + + class PieChart {} + + class CakeChart : PieChart {} + + class ClassWrapper { + public Object someClass; + + this(Object someClass) { + this.someClass = someClass; + } + } + + class ClassWrapperWrapper { + public ClassWrapper wrapper; + + this(ClassWrapper wrapper) { + this.wrapper = wrapper; + } + } + + class SimpleContext : ApplicationContext { + public override void registerDependencies(shared(DependencyContainer) container) { + container.register!CakeChart; + } + + @Component + public Apple apple() { + return new Apple(); + } + } + + class ComplexAutowiredTestContext : ApplicationContext { + + @Autowire + private Apple apple; + + @Autowire + protected ClassWrapper classWrapper; + + public override void registerDependencies(shared(DependencyContainer) container) { + container.register!Apple; + } + + @Component + public ClassWrapper wrapper() { + return new ClassWrapper(apple); + } + + @Component + public ClassWrapperWrapper wrapperWrapper() { + return new ClassWrapperWrapper(classWrapper); + } + + } + + class AutowiredTestContext : ApplicationContext { + + @Autowire + private Apple apple; + + @Component + public ClassWrapper wrapper() { + return new ClassWrapper(apple); + } + } + + class TestContext : ApplicationContext { + + @Component + public Banana banana() { + return new Banana("Yellow"); + } + + public Apple apple() { + return new Apple(); + } + + @Component + @RegisterByType!Fruit + public Pear pear() { + return new Pear(); + } + + @Component + @RegisterByType!Animal + public Rabbit rabbit() { + return new Rabbit(); + } + + @Component + @RegisterByType!Animal + public Wolf wolf() { + return new Wolf(); + } + + @Component + @Prototype + public PieChart pieChart() { + return new PieChart(); + } + } + + class TestImplementation : TestInterface { + public string someContent = ""; + } + + class SomeOtherClassThen { + } + + class ClassWithConstructor { + public TestImplementation testImplementation; + + this(TestImplementation testImplementation) { + this.testImplementation = testImplementation; + } + } + + class ClassWithMultipleConstructors { + public SomeOtherClassThen someOtherClassThen; + public TestImplementation testImplementation; + + this(SomeOtherClassThen someOtherClassThen) { + this.someOtherClassThen = someOtherClassThen; + } + + this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { + this.someOtherClassThen = someOtherClassThen; + this.testImplementation = testImplementation; + } + } + + class ClassWithConstructorWithMultipleParameters { + public SomeOtherClassThen someOtherClassThen; + public TestImplementation testImplementation; + + this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { + this.someOtherClassThen = someOtherClassThen; + this.testImplementation = testImplementation; + } + } + + class ClassWithPrimitiveConstructor { + public SomeOtherClassThen someOtherClassThen; + + this(string willNotBePicked) { + } + + this(SomeOtherClassThen someOtherClassThen) { + this.someOtherClassThen = someOtherClassThen; + } + } + + class ClassWithEmptyConstructor { + public SomeOtherClassThen someOtherClassThen; + + this() { + } + + this(SomeOtherClassThen someOtherClassThen) { + this.someOtherClassThen = someOtherClassThen; + } + } + + class ClassWithNonInjectableConstructor { + this(string myName) { + } + } + + class TestType {} + + class Dependency {} + + struct Thing { + int x; + } + + class MyConfig { + @Value("conf.stuffs") + int stuffs; + + @Value("conf.name") + string name; + + @Value("conf.thing") + Thing thing; + } + + class ConfigWithDefaults { + @Value("conf.missing") + int noms = 9; + } + + class ConfigWithMandatory { + @MandatoryValue("conf.mustbethere") + int nums; + } + + class IntInjector : ValueInjector!int { + public override int get(string key) { + assert(key == "conf.stuffs"); + return 364; + } + } + + class StringInjector : ValueInjector!string { + public override string get(string key) { + assert(key == "conf.name"); + return "Le Chef"; + } + } + + class ThingInjector : ValueInjector!Thing { + public override Thing get(string key) { + assert(key == "conf.thing"); + return Thing(8899); + } + } + + class DefaultIntInjector : ValueInjector!int { + public override int get(string key) { + throw new ValueNotAvailableException(key); + } + } + + class MandatoryAvailableIntInjector : ValueInjector!int { + public override int get(string key) { + return 7466; + } + } + + class MandatoryUnavailableIntInjector : ValueInjector!int { + public override int get(string key) { + throw new ValueNotAvailableException(key); + } + } + + class DependencyInjectedIntInjector : ValueInjector!int { + @Autowire + public Dependency dependency; + + public override int get(string key) { + return 2345; + } + } + + class CircularIntInjector : ValueInjector!int { + @Autowire + public ValueInjector!int dependency; + + private int count = 0; + + public override int get(string key) { + count += 1; + if (count >= 3) { + return count; + } + return dependency.get(key); + } + } + + class ValueInjectedIntInjector : ValueInjector!int { + @Value("five") + public int count = 0; + + public override int get(string key) { + if (key == "five") { + return 5; + } + + return count; + } + } + + class DependencyValueInjectedIntInjector : ValueInjector!int { + @Autowire + public ConfigWithDefaults config; + + public override int get(string key) { + if (key == "conf.missing") { + return 8899; + } + + return 0; + } + } } diff --git a/test/poodinis/testmain.d b/test/poodinis/testmain.d index 71c6cd5..8301472 100644 --- a/test/poodinis/testmain.d +++ b/test/poodinis/testmain.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ diff --git a/test/poodinis/valueinjectiontest.d b/test/poodinis/valueinjectiontest.d index fbb8e4d..7f93409 100644 --- a/test/poodinis/valueinjectiontest.d +++ b/test/poodinis/valueinjectiontest.d @@ -1,6 +1,6 @@ /** * Poodinis Dependency Injection Framework - * Copyright 2014-2017 Mike Bierlee + * Copyright 2014-2018 Mike Bierlee * This software is licensed under the terms of the MIT license. * The full terms of the license can be found in the LICENSE file. */ @@ -12,126 +12,126 @@ import std.exception; version(unittest) { - struct LocalStruct { - bool wasInjected = false; - } + struct LocalStruct { + bool wasInjected = false; + } - class LocalStructInjector : ValueInjector!LocalStruct { - public override LocalStruct get(string key) { - auto data = LocalStruct(true); - return data; - } - } + class LocalStructInjector : ValueInjector!LocalStruct { + public override LocalStruct get(string key) { + auto data = LocalStruct(true); + return data; + } + } - class LocalClassWithStruct { - @Value("") - public LocalStruct localStruct; - } + class LocalClassWithStruct { + @Value("") + public LocalStruct localStruct; + } - // Test injection of values - unittest { - auto container = new shared DependencyContainer(); - container.register!MyConfig; - container.register!(ValueInjector!int, IntInjector); - container.register!(ValueInjector!string, StringInjector); - container.register!(ValueInjector!Thing, ThingInjector); + // Test injection of values + unittest { + auto container = new shared DependencyContainer(); + container.register!MyConfig; + container.register!(ValueInjector!int, IntInjector); + container.register!(ValueInjector!string, StringInjector); + container.register!(ValueInjector!Thing, ThingInjector); - auto instance = container.resolve!MyConfig; - assert(instance.stuffs == 364); - assert(instance.name == "Le Chef"); - assert(instance.thing.x == 8899); - } + auto instance = container.resolve!MyConfig; + assert(instance.stuffs == 364); + assert(instance.name == "Le Chef"); + assert(instance.thing.x == 8899); + } - // Test injection of values throws exception when injector is not there - unittest { - auto container = new shared DependencyContainer(); - container.register!MyConfig; - assertThrown!ResolveException(container.resolve!MyConfig); + // Test injection of values throws exception when injector is not there + unittest { + auto container = new shared DependencyContainer(); + container.register!MyConfig; + assertThrown!ResolveException(container.resolve!MyConfig); - assertThrown!ValueInjectionException(autowire(container, new MyConfig())); - } + assertThrown!ValueInjectionException(autowire(container, new MyConfig())); + } - // Test injection of values with defaults - unittest { - auto container = new shared DependencyContainer(); - container.register!ConfigWithDefaults; - container.register!(ValueInjector!int, DefaultIntInjector); + // Test injection of values with defaults + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithDefaults; + container.register!(ValueInjector!int, DefaultIntInjector); - auto instance = container.resolve!ConfigWithDefaults; - assert(instance.noms == 9); - } + auto instance = container.resolve!ConfigWithDefaults; + assert(instance.noms == 9); + } - // Test mandatory injection of values which are available - unittest { - auto container = new shared DependencyContainer(); - container.register!ConfigWithMandatory; - container.register!(ValueInjector!int, MandatoryAvailableIntInjector); + // Test mandatory injection of values which are available + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithMandatory; + container.register!(ValueInjector!int, MandatoryAvailableIntInjector); - auto instance = container.resolve!ConfigWithMandatory; - assert(instance.nums == 7466); - } + auto instance = container.resolve!ConfigWithMandatory; + assert(instance.nums == 7466); + } - // Test mandatory injection of values which are not available - unittest { - auto container = new shared DependencyContainer(); - container.register!ConfigWithMandatory; - container.register!(ValueInjector!int, MandatoryUnavailableIntInjector); + // Test mandatory injection of values which are not available + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithMandatory; + container.register!(ValueInjector!int, MandatoryUnavailableIntInjector); - assertThrown!ResolveException(container.resolve!ConfigWithMandatory); - assertThrown!ValueInjectionException(autowire(container, new ConfigWithMandatory())); - } + assertThrown!ResolveException(container.resolve!ConfigWithMandatory); + assertThrown!ValueInjectionException(autowire(container, new ConfigWithMandatory())); + } - // Test injecting dependencies within value injectors - unittest { - auto container = new shared DependencyContainer(); - auto dependency = new Dependency(); - container.register!Dependency.existingInstance(dependency); - container.register!(ValueInjector!int, DependencyInjectedIntInjector); - auto injector = cast(DependencyInjectedIntInjector) container.resolve!(ValueInjector!int); + // Test injecting dependencies within value injectors + unittest { + auto container = new shared DependencyContainer(); + auto dependency = new Dependency(); + container.register!Dependency.existingInstance(dependency); + container.register!(ValueInjector!int, DependencyInjectedIntInjector); + auto injector = cast(DependencyInjectedIntInjector) container.resolve!(ValueInjector!int); - assert(injector.dependency is dependency); - } + assert(injector.dependency is dependency); + } - // Test injecting circular dependencies within value injectors - unittest { - auto container = new shared DependencyContainer(); - container.register!(ValueInjector!int, CircularIntInjector); - auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int); + // Test injecting circular dependencies within value injectors + unittest { + auto container = new shared DependencyContainer(); + container.register!(ValueInjector!int, CircularIntInjector); + auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int); - assert(injector.dependency is injector); - assert(injector.get("whatever") == 3); - } + assert(injector.dependency is injector); + assert(injector.get("whatever") == 3); + } - // Test value injection within value injectors - unittest { - auto container = new shared DependencyContainer(); - container.register!(ValueInjector!int, ValueInjectedIntInjector); - auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int); + // Test value injection within value injectors + unittest { + auto container = new shared DependencyContainer(); + container.register!(ValueInjector!int, ValueInjectedIntInjector); + auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int); - assert(injector.count == 5); - } + assert(injector.count == 5); + } - // Test value injection within dependencies of value injectors - unittest { - auto container = new shared DependencyContainer(); - container.register!ConfigWithDefaults; + // Test value injection within dependencies of value injectors + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithDefaults; - container.register!(ValueInjector!int, DependencyValueInjectedIntInjector); - auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(ValueInjector!int); + container.register!(ValueInjector!int, DependencyValueInjectedIntInjector); + auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(ValueInjector!int); - assert(injector.config.noms == 8899); - } + assert(injector.config.noms == 8899); + } - // Test resolving locally defined struct injector (github issue #20) - unittest { - auto container = new shared DependencyContainer(); - container.register!(ValueInjector!LocalStruct, LocalStructInjector); - container.register!LocalClassWithStruct; + // Test resolving locally defined struct injector (github issue #20) + unittest { + auto container = new shared DependencyContainer(); + container.register!(ValueInjector!LocalStruct, LocalStructInjector); + container.register!LocalClassWithStruct; - auto injector = container.resolve!(ValueInjector!LocalStruct); - assert(injector !is null); + auto injector = container.resolve!(ValueInjector!LocalStruct); + assert(injector !is null); - auto localClass = container.resolve!LocalClassWithStruct; - assert(localClass.localStruct.wasInjected); - } + auto localClass = container.resolve!LocalClassWithStruct; + assert(localClass.localStruct.wasInjected); + } }