mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Update copyrigths
And convert tabs to spaces
This commit is contained in:
parent
9d0bbfd6cf
commit
4410206ec4
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,3 +19,4 @@
|
||||||
/.idea
|
/.idea
|
||||||
/*.iml
|
/*.iml
|
||||||
/out
|
/out
|
||||||
|
/classes
|
|
@ -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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Poodinis Dependency Injection Framework
|
Poodinis Dependency Injection Framework
|
||||||
=======================================
|
=======================================
|
||||||
Version 8.0.1
|
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)
|
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)
|
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)
|
||||||
|
|
|
@ -83,7 +83,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -155,7 +155,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -101,7 +101,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -93,7 +93,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -104,7 +104,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -177,7 +177,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -207,7 +207,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -162,7 +162,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -97,7 +97,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -189,7 +189,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -109,7 +109,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -91,7 +91,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -96,7 +96,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -96,7 +96,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -107,7 +107,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -116,7 +116,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -142,7 +142,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -100,7 +100,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -83,7 +83,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -102,7 +102,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
Mike Bierlee (m.bierlee@lostmoment.com)
|
Mike Bierlee (m.bierlee@lostmoment.com)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2017 Mike Bierlee
|
<p>Copyright Digital Mars 2005 - 2009., Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-., 2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>boost.org/LICENSE_1_0.txt, Boost License 1.0
|
<p>boost.org/LICENSE_1_0.txt, Boost License 1.0
|
||||||
|
|
|
@ -121,7 +121,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -97,7 +97,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -95,7 +95,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -98,7 +98,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -156,7 +156,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -120,7 +120,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -120,7 +120,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -106,7 +106,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -103,7 +103,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -128,7 +128,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
|
@ -92,7 +92,7 @@ document.getElementById('symbolSearchPane').style.display = 'block';</script>
|
||||||
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
<p>Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>2014-2017 Mike Bierlee
|
<p>2014-2018 Mike Bierlee
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>This software is licensed under the terms of the MIT license.
|
<p>This software is licensed under the terms of the MIT license.
|
||||||
|
|
2
dub.json
2
dub.json
|
@ -3,7 +3,7 @@
|
||||||
"description" : "A dependency injection framework with support for autowiring.",
|
"description" : "A dependency injection framework with support for autowiring.",
|
||||||
"homepage": "http://lostmoment.com/open-source/poodinis",
|
"homepage": "http://lostmoment.com/open-source/poodinis",
|
||||||
"authors": ["Mike Bierlee"],
|
"authors": ["Mike Bierlee"],
|
||||||
"copyright": "Copyright 2014-2017 Mike Bierlee",
|
"copyright": "Copyright 2014-2018 Mike Bierlee",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"-ddoxTool": "scod",
|
"-ddoxTool": "scod",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* 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.traits;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
|
||||||
private struct UseMemberType {};
|
private struct UseMemberType {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UDA for annotating class members as candidates for autowiring.
|
* 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"
|
* will also be autowired because the autowire mechanism knows that member "fuelEngine" is an instance of "FuelEngine"
|
||||||
*/
|
*/
|
||||||
struct Autowire(QualifierType) {
|
struct Autowire(QualifierType) {
|
||||||
QualifierType qualifier;
|
QualifierType qualifier;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UDA for marking autowired dependencies optional.
|
* UDA for marking autowired dependencies optional.
|
||||||
* Optional dependencies will not lead to a resolveException when there is no type registered for them.
|
* Optional dependencies will not lead to a resolveException when there is no type registered for them.
|
||||||
* The member will remain null.
|
* 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.
|
* 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 {}
|
struct AssignNewInstance {}
|
||||||
|
|
||||||
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) {
|
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
|
* See_Also: Autowire
|
||||||
*/
|
*/
|
||||||
public void autowire(Type)(shared(DependencyContainer) container, Type instance) {
|
public void autowire(Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugAutowiredInstance(typeid(Type), &instance);
|
printDebugAutowiredInstance(typeid(Type), &instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recurse into base class if there are more between Type and Object in the hierarchy
|
// Recurse into base class if there are more between Type and Object in the hierarchy
|
||||||
static if(BaseClassesTuple!Type.length > 1)
|
static if(BaseClassesTuple!Type.length > 1)
|
||||||
{
|
{
|
||||||
autowire!(BaseClassesTuple!Type[0])(container, instance);
|
autowire!(BaseClassesTuple!Type[0])(container, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(index, name; FieldNameTuple!Type) {
|
foreach(index, name; FieldNameTuple!Type) {
|
||||||
autowireMember!(name, index, Type)(container, instance);
|
autowireMember!(name, index, Type)(container, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType, void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) {
|
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) {
|
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) {
|
private void autowireMember(string member, size_t memberIndex, Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
foreach(attribute; __traits(getAttributes, Type.tupleof[memberIndex])) {
|
foreach(attribute; __traits(getAttributes, Type.tupleof[memberIndex])) {
|
||||||
static if (is(attribute == Autowire!T, T)) {
|
static if (is(attribute == Autowire!T, T)) {
|
||||||
injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance);
|
injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance);
|
||||||
} else static if (__traits(isSame, attribute, Autowire)) {
|
} else static if (__traits(isSame, attribute, Autowire)) {
|
||||||
injectInstance!(member, memberIndex, UseMemberType)(container, instance);
|
injectInstance!(member, memberIndex, UseMemberType)(container, instance);
|
||||||
} else static if (is(typeof(attribute) == Value)) {
|
} else static if (is(typeof(attribute) == Value)) {
|
||||||
enum key = attribute.key;
|
enum key = attribute.key;
|
||||||
injectValue!(member, memberIndex, key, false)(container, instance);
|
injectValue!(member, memberIndex, key, false)(container, instance);
|
||||||
} else static if (is(typeof(attribute) == MandatoryValue)) {
|
} else static if (is(typeof(attribute) == MandatoryValue)) {
|
||||||
enum key = attribute.key;
|
enum key = attribute.key;
|
||||||
injectValue!(member, memberIndex, key, true)(container, instance);
|
injectValue!(member, memberIndex, key, true)(container, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(shared(DependencyContainer) container, Type instance) {
|
private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
if (instance.tupleof[memberIndex] is null) {
|
if (instance.tupleof[memberIndex] is null) {
|
||||||
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
||||||
enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency);
|
enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency);
|
||||||
|
|
||||||
static if (isDynamicArray!MemberType) {
|
static if (isDynamicArray!MemberType) {
|
||||||
injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, instance);
|
injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, instance);
|
||||||
} else {
|
} else {
|
||||||
injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container, instance);
|
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) {
|
private void injectMultipleInstances(string member, size_t memberIndex, bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
alias MemberElementType = ElementType!MemberType;
|
alias MemberElementType = ElementType!MemberType;
|
||||||
static if (isOptional) {
|
static if (isOptional) {
|
||||||
auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
|
auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
|
||||||
} else {
|
} else {
|
||||||
auto instances = container.resolveAll!MemberElementType;
|
auto instances = container.resolveAll!MemberElementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.tupleof[memberIndex] = instances;
|
instance.tupleof[memberIndex] = instances;
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
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) {
|
private void injectSingleInstance(string member, size_t memberIndex, bool isOptional, MemberType, QualifierType, Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance);
|
enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance);
|
||||||
|
|
||||||
MemberType qualifiedInstance;
|
MemberType qualifiedInstance;
|
||||||
static if (!is(QualifierType == UseMemberType)) {
|
static if (!is(QualifierType == UseMemberType)) {
|
||||||
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance, isOptional)(container);
|
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance, isOptional)(container);
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
qualifiedInstanceType = typeid(QualifierType);
|
qualifiedInstanceType = typeid(QualifierType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance, isOptional)(container);
|
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance, isOptional)(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.tupleof[memberIndex] = qualifiedInstance;
|
instance.tupleof[memberIndex] = qualifiedInstance;
|
||||||
|
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew, bool isOptional)(shared(DependencyContainer) container) {
|
private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew, bool isOptional)(shared(DependencyContainer) container) {
|
||||||
static if (createNew) {
|
static if (createNew) {
|
||||||
auto instanceFactory = new InstanceFactory();
|
auto instanceFactory = new InstanceFactory();
|
||||||
instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), CreatesSingleton.no);
|
instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), CreatesSingleton.no);
|
||||||
return cast(MemberType) instanceFactory.getInstance();
|
return cast(MemberType) instanceFactory.getInstance();
|
||||||
} else {
|
} else {
|
||||||
static if (isOptional) {
|
static if (isOptional) {
|
||||||
return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
|
return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
|
||||||
} else {
|
} else {
|
||||||
return container.resolve!(MemberType, QualifierType);
|
return container.resolve!(MemberType, QualifierType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(shared(DependencyContainer) container, Type instance) {
|
private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
||||||
try {
|
try {
|
||||||
auto injector = container.resolve!(ValueInjector!MemberType);
|
auto injector = container.resolve!(ValueInjector!MemberType);
|
||||||
instance.tupleof[memberIndex] = injector.get(key);
|
instance.tupleof[memberIndex] = injector.get(key);
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
|
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
|
||||||
}
|
}
|
||||||
} catch (ResolveException e) {
|
} 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));
|
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) {
|
} catch (ValueNotAvailableException e) {
|
||||||
static if (mandatory) {
|
static if (mandatory) {
|
||||||
throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s", typeid(MemberType), typeid(Type), member), e);
|
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) {
|
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().
|
* Deprecated: Using the global container is undesired. See DependencyContainer.getInstance().
|
||||||
*/
|
*/
|
||||||
public deprecated void globalAutowire(Type)(Type instance) {
|
public deprecated void globalAutowire(Type)(Type instance) {
|
||||||
DependencyContainer.getInstance().autowire(instance);
|
DependencyContainer.getInstance().autowire(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowiredRegistration(RegistrationType : Object) : Registration {
|
class AutowiredRegistration(RegistrationType : Object) : Registration {
|
||||||
private shared(DependencyContainer) container;
|
private shared(DependencyContainer) container;
|
||||||
|
|
||||||
public this(TypeInfo registeredType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
|
public this(TypeInfo registeredType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
|
||||||
super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer);
|
super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Object getInstance(InstantiationContext context = new AutowireInstantiationContext()) {
|
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.");
|
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;
|
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!");
|
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) {
|
if (autowireContext.autowireInstance) {
|
||||||
originatingContainer.autowire(instance);
|
originatingContainer.autowire(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.preDestructor = getPreDestructor(instance);
|
this.preDestructor = getPreDestructor(instance);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void delegate() getPreDestructor(RegistrationType instance) {
|
private void delegate() getPreDestructor(RegistrationType instance) {
|
||||||
void delegate() preDestructor = null;
|
void delegate() preDestructor = null;
|
||||||
foreach (memberName; __traits(allMembers, RegistrationType)) {
|
foreach (memberName; __traits(allMembers, RegistrationType)) {
|
||||||
mixin(createImportsString!RegistrationType);
|
mixin(createImportsString!RegistrationType);
|
||||||
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
||||||
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
||||||
&& isFunction!(mixin(fullyQualifiedName!RegistrationType ~ `.` ~ memberName))
|
&& isFunction!(mixin(fullyQualifiedName!RegistrationType ~ `.` ~ memberName))
|
||||||
&& hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) {
|
&& hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) {
|
||||||
preDestructor = &__traits(getMember, instance, memberName);
|
preDestructor = &__traits(getMember, instance, memberName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return preDestructor;
|
return preDestructor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowireInstantiationContext : InstantiationContext {
|
class AutowireInstantiationContext : InstantiationContext {
|
||||||
public bool autowireInstance = true;
|
public bool autowireInstance = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
|
@ -27,60 +27,60 @@ import std.concurrency;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
debug {
|
debug {
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when errors occur while resolving a type in a dependency container.
|
* Exception thrown when errors occur while resolving a type in a dependency container.
|
||||||
*/
|
*/
|
||||||
class ResolveException : Exception {
|
class ResolveException : Exception {
|
||||||
this(string message, TypeInfo resolveType) {
|
this(string message, TypeInfo resolveType) {
|
||||||
super(format("Exception while resolving type %s: %s", resolveType.toString(), message));
|
super(format("Exception while resolving type %s: %s", resolveType.toString(), message));
|
||||||
}
|
}
|
||||||
|
|
||||||
this(Throwable cause, TypeInfo resolveType) {
|
this(Throwable cause, TypeInfo resolveType) {
|
||||||
super(format("Exception while resolving type %s", resolveType.toString()), cause);
|
super(format("Exception while resolving type %s", resolveType.toString()), cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when errors occur while registering a type in a dependency container.
|
* Exception thrown when errors occur while registering a type in a dependency container.
|
||||||
*/
|
*/
|
||||||
class RegistrationException : Exception {
|
class RegistrationException : Exception {
|
||||||
this(string message, TypeInfo registrationType) {
|
this(string message, TypeInfo registrationType) {
|
||||||
super(format("Exception while registering type %s: %s", registrationType.toString(), message));
|
super(format("Exception while registering type %s: %s", registrationType.toString(), message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options which influence the process of registering dependencies
|
* Options which influence the process of registering dependencies
|
||||||
*/
|
*/
|
||||||
public enum RegistrationOption {
|
public enum RegistrationOption {
|
||||||
none = 0,
|
none = 0,
|
||||||
/**
|
/**
|
||||||
* Prevent a concrete type being registered on itself. With this option you will always need
|
* 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.
|
* to use the supertype as the type of the dependency.
|
||||||
*/
|
*/
|
||||||
doNotAddConcreteTypeRegistration = 1 << 0,
|
doNotAddConcreteTypeRegistration = 1 << 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options which influence the process of resolving dependencies
|
* Options which influence the process of resolving dependencies
|
||||||
*/
|
*/
|
||||||
public enum ResolveOption {
|
public enum ResolveOption {
|
||||||
none = 0,
|
none = 0,
|
||||||
/**
|
/**
|
||||||
* Registers the type you're trying to resolve before returning it.
|
* Registers the type you're trying to resolve before returning it.
|
||||||
* This essentially makes registration optional for resolving by concerete types.
|
* This essentially makes registration optional for resolving by concerete types.
|
||||||
* Resolinvg will still fail when trying to resolve a dependency by supertype.
|
* Resolinvg will still fail when trying to resolve a dependency by supertype.
|
||||||
*/
|
*/
|
||||||
registerBeforeResolving = 1 << 0,
|
registerBeforeResolving = 1 << 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does not throw a resolve exception when a type is not registered but will
|
* 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.
|
* return null instead. If the type is an array, an empty array is returned instead.
|
||||||
*/
|
*/
|
||||||
noResolveException = 1 << 1
|
noResolveException = 1 << 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,358 +112,358 @@ struct PreDestroy {}
|
||||||
* You can still create new instances of this class for exceptional situations.
|
* You can still create new instances of this class for exceptional situations.
|
||||||
*/
|
*/
|
||||||
synchronized class DependencyContainer {
|
synchronized class DependencyContainer {
|
||||||
private Registration[][TypeInfo] registrations;
|
private Registration[][TypeInfo] registrations;
|
||||||
|
|
||||||
private Registration[] autowireStack;
|
private Registration[] autowireStack;
|
||||||
|
|
||||||
private RegistrationOption persistentRegistrationOptions;
|
private RegistrationOption persistentRegistrationOptions;
|
||||||
private ResolveOption persistentResolveOptions;
|
private ResolveOption persistentResolveOptions;
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
clearAllRegistrations();
|
clearAllRegistrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency by concrete class type.
|
* Register a dependency by concrete class type.
|
||||||
*
|
*
|
||||||
* A dependency registered by concrete class type can only be resolved 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.
|
* No qualifiers can be used when resolving dependencies which are registered by concrete type.
|
||||||
*
|
*
|
||||||
* The default registration scope is "single instance" scope.
|
* The default registration scope is "single instance" scope.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* A registration is returned which can be used to change the registration scope.
|
* A registration is returned which can be used to change the registration scope.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* Register and resolve a class by concrete type:
|
* Register and resolve a class by concrete type:
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* container.register!Cat;
|
* container.register!Cat;
|
||||||
* ---
|
* ---
|
||||||
*
|
*
|
||||||
* See_Also: singleInstance, newInstance, existingInstance
|
* See_Also: singleInstance, newInstance, existingInstance
|
||||||
*/
|
*/
|
||||||
public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) {
|
public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) {
|
||||||
return register!(ConcreteType, ConcreteType)(options);
|
return register!(ConcreteType, ConcreteType)(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency by super type.
|
* Register a dependency by super type.
|
||||||
*
|
*
|
||||||
* A dependency registered by super type can only be resolved by super type. A qualifier is typically
|
* 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.
|
* used to resolve dependencies registered by super type.
|
||||||
*
|
*
|
||||||
* The default registration scope is "single instance" scope.
|
* The default registration scope is "single instance" scope.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* Register and resolve by super type
|
* Register and resolve by super type
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* container.register!(Animal, Cat);
|
* container.register!(Animal, Cat);
|
||||||
* ---
|
* ---
|
||||||
*
|
*
|
||||||
* See_Also: singleInstance, newInstance, existingInstance, RegistrationOption
|
* See_Also: singleInstance, newInstance, existingInstance, RegistrationOption
|
||||||
*/
|
*/
|
||||||
public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) {
|
public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) {
|
||||||
TypeInfo registeredType = typeid(SuperType);
|
TypeInfo registeredType = typeid(SuperType);
|
||||||
TypeInfo_Class concreteType = typeid(ConcreteType);
|
TypeInfo_Class concreteType = typeid(ConcreteType);
|
||||||
|
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString()));
|
writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
||||||
if (existingRegistration) {
|
if (existingRegistration) {
|
||||||
return existingRegistration;
|
return existingRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto instanceFactory = new ConstructorInjectingInstanceFactory!ConcreteType(this);
|
auto instanceFactory = new ConstructorInjectingInstanceFactory!ConcreteType(this);
|
||||||
auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this);
|
auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this);
|
||||||
newRegistration.singleInstance();
|
newRegistration.singleInstance();
|
||||||
|
|
||||||
static if (!is(SuperType == ConcreteType)) {
|
static if (!is(SuperType == ConcreteType)) {
|
||||||
if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) {
|
if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) {
|
||||||
auto concreteTypeRegistration = register!ConcreteType;
|
auto concreteTypeRegistration = register!ConcreteType;
|
||||||
concreteTypeRegistration.linkTo(newRegistration);
|
concreteTypeRegistration.linkTo(newRegistration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registrations[registeredType] ~= cast(shared(Registration)) newRegistration;
|
registrations[registeredType] ~= cast(shared(Registration)) newRegistration;
|
||||||
return newRegistration;
|
return newRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
||||||
return ((options | persistentOptions) & option) != 0;
|
return ((options | persistentOptions) & option) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OptionType buildFlags(OptionType)(OptionType[] options) {
|
private OptionType buildFlags(OptionType)(OptionType[] options) {
|
||||||
OptionType flags;
|
OptionType flags;
|
||||||
foreach (option; options) {
|
foreach (option; options) {
|
||||||
flags |= option;
|
flags |= option;
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) {
|
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) {
|
||||||
auto existingCandidates = registrationType in registrations;
|
auto existingCandidates = registrationType in registrations;
|
||||||
if (existingCandidates) {
|
if (existingCandidates) {
|
||||||
return getRegistration(cast(Registration[]) *existingCandidates, qualifierType);
|
return getRegistration(cast(Registration[]) *existingCandidates, qualifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) {
|
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) {
|
||||||
foreach(existingRegistration ; candidates) {
|
foreach(existingRegistration ; candidates) {
|
||||||
if (existingRegistration.instanceType == concreteType) {
|
if (existingRegistration.instanceType == concreteType) {
|
||||||
return existingRegistration;
|
return existingRegistration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve dependencies.
|
* Resolve dependencies.
|
||||||
*
|
*
|
||||||
* Dependencies can only resolved using this method if they are registered by concrete type or the only
|
* Dependencies can only resolved using this method if they are registered by concrete type or the only
|
||||||
* concrete type registered by super type.
|
* concrete type registered by super type.
|
||||||
*
|
*
|
||||||
* Resolved dependencies are automatically autowired before being returned.
|
* Resolved dependencies are automatically autowired before being returned.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* An instance is returned which is created according to the registration scope with which they are registered.
|
* An instance is returned which is created according to the registration scope with which they are registered.
|
||||||
*
|
*
|
||||||
* Throws:
|
* Throws:
|
||||||
* ResolveException when type is not registered.
|
* ResolveException when type is not registered.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* Resolve dependencies registered by super type and concrete type:
|
* Resolve dependencies registered by super type and concrete type:
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* class Dog : Animal { ... }
|
* class Dog : Animal { ... }
|
||||||
*
|
*
|
||||||
* container.register!(Animal, Cat);
|
* container.register!(Animal, Cat);
|
||||||
* container.register!Dog;
|
* container.register!Dog;
|
||||||
*
|
*
|
||||||
* container.resolve!Animal;
|
* container.resolve!Animal;
|
||||||
* container.resolve!Dog;
|
* container.resolve!Dog;
|
||||||
* ---
|
* ---
|
||||||
* You cannot resolve a dependency when it is registered by multiple super types:
|
* You cannot resolve a dependency when it is registered by multiple super types:
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* class Dog : Animal { ... }
|
* class Dog : Animal { ... }
|
||||||
*
|
*
|
||||||
* container.register!(Animal, Cat);
|
* container.register!(Animal, Cat);
|
||||||
* container.register!(Animal, Dog);
|
* container.register!(Animal, Dog);
|
||||||
*
|
*
|
||||||
* container.resolve!Animal; // Error: multiple candidates for type "Animal"
|
* 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"
|
* 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.
|
* You need to use the resolve method which allows you to specify a qualifier.
|
||||||
*/
|
*/
|
||||||
public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
||||||
return resolve!(RegistrationType, RegistrationType)(resolveOptions);
|
return resolve!(RegistrationType, RegistrationType)(resolveOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve dependencies using a qualifier.
|
* Resolve dependencies using a qualifier.
|
||||||
*
|
*
|
||||||
* Dependencies can only resolved using this method if they are registered by super type.
|
* Dependencies can only resolved using this method if they are registered by super type.
|
||||||
*
|
*
|
||||||
* Resolved dependencies are automatically autowired before being returned.
|
* Resolved dependencies are automatically autowired before being returned.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* An instance is returned which is created according to the registration scope with which they are registered.
|
* An instance is returned which is created according to the registration scope with which they are registered.
|
||||||
*
|
*
|
||||||
* Throws:
|
* Throws:
|
||||||
* ResolveException when type is not registered or there are multiple candidates available for type.
|
* ResolveException when type is not registered or there are multiple candidates available for type.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* Resolve dependencies registered by super type:
|
* Resolve dependencies registered by super type:
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* class Dog : Animal { ... }
|
* class Dog : Animal { ... }
|
||||||
*
|
*
|
||||||
* container.register!(Animal, Cat);
|
* container.register!(Animal, Cat);
|
||||||
* container.register!(Animal, Dog);
|
* container.register!(Animal, Dog);
|
||||||
*
|
*
|
||||||
* container.resolve!(Animal, Cat);
|
* container.resolve!(Animal, Cat);
|
||||||
* container.resolve!(Animal, Dog);
|
* container.resolve!(Animal, Dog);
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
||||||
TypeInfo resolveType = typeid(RegistrationType);
|
TypeInfo resolveType = typeid(RegistrationType);
|
||||||
TypeInfo qualifierType = typeid(QualifierType);
|
TypeInfo qualifierType = typeid(QualifierType);
|
||||||
|
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString());
|
writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (__traits(compiles, new QualifierType())) {
|
static if (__traits(compiles, new QualifierType())) {
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.registerBeforeResolving)) {
|
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.registerBeforeResolving)) {
|
||||||
register!(RegistrationType, QualifierType)();
|
register!(RegistrationType, QualifierType)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto candidates = resolveType in registrations;
|
auto candidates = resolveType in registrations;
|
||||||
if (!candidates) {
|
if (!candidates) {
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) {
|
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) {
|
||||||
return null;
|
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 {
|
try {
|
||||||
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
|
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
|
||||||
callPostConstructors(newInstance);
|
callPostConstructors(newInstance);
|
||||||
return newInstance;
|
return newInstance;
|
||||||
} catch (ValueInjectionException e) {
|
} catch (ValueInjectionException e) {
|
||||||
throw new ResolveException(e, resolveType);
|
throw new ResolveException(e, resolveType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
|
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
|
||||||
QualifierType instance;
|
QualifierType instance;
|
||||||
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
|
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
|
||||||
autowireStack ~= cast(shared(Registration)) registration;
|
autowireStack ~= cast(shared(Registration)) registration;
|
||||||
instance = cast(QualifierType) registration.getInstance(new AutowireInstantiationContext());
|
instance = cast(QualifierType) registration.getInstance(new AutowireInstantiationContext());
|
||||||
autowireStack = autowireStack[0 .. $-1];
|
autowireStack = autowireStack[0 .. $-1];
|
||||||
} else {
|
} else {
|
||||||
auto autowireContext = new AutowireInstantiationContext();
|
auto autowireContext = new AutowireInstantiationContext();
|
||||||
autowireContext.autowireInstance = false;
|
autowireContext.autowireInstance = false;
|
||||||
instance = cast(QualifierType) registration.getInstance(autowireContext);
|
instance = cast(QualifierType) registration.getInstance(autowireContext);
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve all dependencies registered to a super type.
|
* Resolve all dependencies registered to a super type.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* An array of autowired instances is returned. The order is undetermined.
|
* An array of autowired instances is returned. The order is undetermined.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* ---
|
* ---
|
||||||
* class Cat : Animal { ... }
|
* class Cat : Animal { ... }
|
||||||
* class Dog : Animal { ... }
|
* class Dog : Animal { ... }
|
||||||
*
|
*
|
||||||
* container.register!(Animal, Cat);
|
* container.register!(Animal, Cat);
|
||||||
* container.register!(Animal, Dog);
|
* container.register!(Animal, Dog);
|
||||||
*
|
*
|
||||||
* Animal[] animals = container.resolveAll!Animal;
|
* Animal[] animals = container.resolveAll!Animal;
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
|
||||||
RegistrationType[] instances;
|
RegistrationType[] instances;
|
||||||
TypeInfo resolveType = typeid(RegistrationType);
|
TypeInfo resolveType = typeid(RegistrationType);
|
||||||
|
|
||||||
auto qualifiedRegistrations = resolveType in registrations;
|
auto qualifiedRegistrations = resolveType in registrations;
|
||||||
if (!qualifiedRegistrations) {
|
if (!qualifiedRegistrations) {
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) {
|
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ResolveException("Type not registered.", resolveType);
|
throw new ResolveException("Type not registered.", resolveType);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(registration ; cast(Registration[]) *qualifiedRegistrations) {
|
foreach(registration ; cast(Registration[]) *qualifiedRegistrations) {
|
||||||
instances ~= resolveAutowiredInstance!RegistrationType(registration);
|
instances ~= resolveAutowiredInstance!RegistrationType(registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) {
|
private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) {
|
||||||
if (resolveType == qualifierType) {
|
if (resolveType == qualifierType) {
|
||||||
if (candidates.length > 1) {
|
if (candidates.length > 1) {
|
||||||
string candidateList = candidates.toConcreteTypeListString();
|
string candidateList = candidates.toConcreteTypeListString();
|
||||||
throw new ResolveException("Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.", resolveType);
|
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) {
|
private void callPostConstructors(Type)(Type instance) {
|
||||||
foreach (memberName; __traits(allMembers, Type)) {
|
foreach (memberName; __traits(allMembers, Type)) {
|
||||||
mixin(createImportsString!Type);
|
mixin(createImportsString!Type);
|
||||||
|
|
||||||
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
||||||
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
||||||
&& isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName))
|
&& isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName))
|
||||||
&& hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) {
|
&& hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) {
|
||||||
__traits(getMember, instance, memberName)();
|
__traits(getMember, instance, memberName)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all dependency registrations managed by this container.
|
* Clears all dependency registrations managed by this container.
|
||||||
*/
|
*/
|
||||||
public void clearAllRegistrations() {
|
public void clearAllRegistrations() {
|
||||||
foreach(registrationsOfType; registrations) {
|
foreach(registrationsOfType; registrations) {
|
||||||
callPreDestructorsOfRegistrations(registrationsOfType);
|
callPreDestructorsOfRegistrations(registrationsOfType);
|
||||||
}
|
}
|
||||||
registrations.destroy();
|
registrations.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a registered dependency by type.
|
* Removes a registered dependency by type.
|
||||||
*
|
*
|
||||||
* A dependency can be removed either by super type or concrete type, depending on how they are registered.
|
* A dependency can be removed either by super type or concrete type, depending on how they are registered.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* ---
|
* ---
|
||||||
* container.removeRegistration!Animal;
|
* container.removeRegistration!Animal;
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
public void removeRegistration(RegistrationType)() {
|
public void removeRegistration(RegistrationType)() {
|
||||||
auto registrationsOfType = *(typeid(RegistrationType) in registrations);
|
auto registrationsOfType = *(typeid(RegistrationType) in registrations);
|
||||||
callPreDestructorsOfRegistrations(registrationsOfType);
|
callPreDestructorsOfRegistrations(registrationsOfType);
|
||||||
registrations.remove(typeid(RegistrationType));
|
registrations.remove(typeid(RegistrationType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) {
|
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) {
|
||||||
foreach(registration; registrations) {
|
foreach(registration; registrations) {
|
||||||
Registration unsharedRegistration = cast(Registration) registration;
|
Registration unsharedRegistration = cast(Registration) registration;
|
||||||
if (unsharedRegistration.preDestructor !is null) {
|
if (unsharedRegistration.preDestructor !is null) {
|
||||||
unsharedRegistration.preDestructor()();
|
unsharedRegistration.preDestructor()();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply persistent registration options which will be used everytime register() is called.
|
* Apply persistent registration options which will be used everytime register() is called.
|
||||||
*/
|
*/
|
||||||
public void setPersistentRegistrationOptions(RegistrationOption options) {
|
public void setPersistentRegistrationOptions(RegistrationOption options) {
|
||||||
persistentRegistrationOptions = options;
|
persistentRegistrationOptions = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsets all applied persistent registration options
|
* Unsets all applied persistent registration options
|
||||||
*/
|
*/
|
||||||
public void unsetPersistentRegistrationOptions() {
|
public void unsetPersistentRegistrationOptions() {
|
||||||
persistentRegistrationOptions = RegistrationOption.none;
|
persistentRegistrationOptions = RegistrationOption.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply persistent resolve options which will be used everytime resolve() is called.
|
* Apply persistent resolve options which will be used everytime resolve() is called.
|
||||||
*/
|
*/
|
||||||
public void setPersistentResolveOptions(ResolveOption options) {
|
public void setPersistentResolveOptions(ResolveOption options) {
|
||||||
persistentResolveOptions = options;
|
persistentResolveOptions = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsets all applied persistent resolve options
|
* Unsets all applied persistent resolve options
|
||||||
*/
|
*/
|
||||||
public void unsetPersistentResolveOptions() {
|
public void unsetPersistentResolveOptions() {
|
||||||
persistentResolveOptions = ResolveOption.none;
|
persistentResolveOptions = ResolveOption.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
|
@ -21,7 +21,7 @@ import poodinis.autowire;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
class ApplicationContext {
|
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.
|
* enables you to use type-qualified alternatives for dependencies.
|
||||||
*/
|
*/
|
||||||
struct RegisterByType(Type) {
|
struct RegisterByType(Type) {
|
||||||
Type type;
|
Type type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,33 +52,33 @@ struct Prototype {}
|
||||||
* want to use annotations to set-up dependencies in your classes.
|
* want to use annotations to set-up dependencies in your classes.
|
||||||
*/
|
*/
|
||||||
public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) {
|
public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) {
|
||||||
auto context = new Context();
|
auto context = new Context();
|
||||||
context.registerDependencies(container);
|
context.registerDependencies(container);
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
container.register!(ApplicationContext, Context)().existingInstance(context);
|
container.register!(ApplicationContext, Context)().existingInstance(context);
|
||||||
autowire(container, context);
|
autowire(container, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) {
|
public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) {
|
||||||
foreach (member ; __traits(allMembers, ApplicationContextType)) {
|
foreach (member ; __traits(allMembers, ApplicationContextType)) {
|
||||||
static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) {
|
static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) {
|
||||||
auto factoryMethod = &__traits(getMember, context, member);
|
auto factoryMethod = &__traits(getMember, context, member);
|
||||||
Registration registration = null;
|
Registration registration = null;
|
||||||
auto createsSingleton = CreatesSingleton.yes;
|
auto createsSingleton = CreatesSingleton.yes;
|
||||||
|
|
||||||
foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) {
|
foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) {
|
||||||
static if (is(attribute == RegisterByType!T, T)) {
|
static if (is(attribute == RegisterByType!T, T)) {
|
||||||
registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod);
|
registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod);
|
||||||
} else static if (__traits(isSame, attribute, Prototype)) {
|
} else static if (__traits(isSame, attribute, Prototype)) {
|
||||||
createsSingleton = CreatesSingleton.no;
|
createsSingleton = CreatesSingleton.no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration is null) {
|
if (registration is null) {
|
||||||
registration = container.register!(ReturnType!factoryMethod);
|
registration = container.register!(ReturnType!factoryMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod);
|
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* 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();
|
alias InstanceFactoryMethod = Object delegate();
|
||||||
|
|
||||||
class InstanceCreationException : Exception {
|
class InstanceCreationException : Exception {
|
||||||
this(string message, string file = __FILE__, size_t line = __LINE__) {
|
this(string message, string file = __FILE__, size_t line = __LINE__) {
|
||||||
super(message, file, line);
|
super(message, file, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstanceFactoryParameters {
|
struct InstanceFactoryParameters {
|
||||||
TypeInfo_Class instanceType;
|
TypeInfo_Class instanceType;
|
||||||
CreatesSingleton createsSingleton = CreatesSingleton.yes;
|
CreatesSingleton createsSingleton = CreatesSingleton.yes;
|
||||||
Object existingInstance;
|
Object existingInstance;
|
||||||
InstanceFactoryMethod factoryMethod;
|
InstanceFactoryMethod factoryMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstanceFactory {
|
class InstanceFactory {
|
||||||
private Object instance = null;
|
private Object instance = null;
|
||||||
private InstanceFactoryParameters _factoryParameters;
|
private InstanceFactoryParameters _factoryParameters;
|
||||||
|
|
||||||
this() {
|
this() {
|
||||||
factoryParameters = InstanceFactoryParameters();
|
factoryParameters = InstanceFactoryParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property void factoryParameters(InstanceFactoryParameters factoryParameters) {
|
public @property void factoryParameters(InstanceFactoryParameters factoryParameters) {
|
||||||
if (factoryParameters.factoryMethod is null) {
|
if (factoryParameters.factoryMethod is null) {
|
||||||
factoryParameters.factoryMethod = &this.createInstance;
|
factoryParameters.factoryMethod = &this.createInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (factoryParameters.existingInstance !is null) {
|
if (factoryParameters.existingInstance !is null) {
|
||||||
factoryParameters.createsSingleton = CreatesSingleton.yes;
|
factoryParameters.createsSingleton = CreatesSingleton.yes;
|
||||||
this.instance = factoryParameters.existingInstance;
|
this.instance = factoryParameters.existingInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
_factoryParameters = factoryParameters;
|
_factoryParameters = factoryParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property InstanceFactoryParameters factoryParameters() {
|
public @property InstanceFactoryParameters factoryParameters() {
|
||||||
return _factoryParameters;
|
return _factoryParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInstance() {
|
public Object getInstance() {
|
||||||
if (_factoryParameters.createsSingleton && instance !is null) {
|
if (_factoryParameters.createsSingleton && instance !is null) {
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugUseExistingInstance();
|
printDebugUseExistingInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugCreateNewInstance();
|
printDebugCreateNewInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
instance = _factoryParameters.factoryMethod();
|
instance = _factoryParameters.factoryMethod();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugUseExistingInstance() {
|
private void printDebugUseExistingInstance() {
|
||||||
if (_factoryParameters.instanceType !is null) {
|
if (_factoryParameters.instanceType !is null) {
|
||||||
writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString()));
|
writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString()));
|
||||||
} else {
|
} else {
|
||||||
writeln("DEBUG: Existing instance returned from custom factory method");
|
writeln("DEBUG: Existing instance returned from custom factory method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugCreateNewInstance() {
|
private void printDebugCreateNewInstance() {
|
||||||
if (_factoryParameters.instanceType !is null) {
|
if (_factoryParameters.instanceType !is null) {
|
||||||
writeln(format("DEBUG: Creating new instance of type %s", _factoryParameters.instanceType.toString()));
|
writeln(format("DEBUG: Creating new instance of type %s", _factoryParameters.instanceType.toString()));
|
||||||
} else {
|
} else {
|
||||||
writeln("DEBUG: Creating new instance from custom factory method");
|
writeln("DEBUG: Creating new instance from custom factory method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object createInstance() {
|
protected Object createInstance() {
|
||||||
enforce!InstanceCreationException(_factoryParameters.instanceType, "Instance type is not defined, cannot create instance without knowing its type.");
|
enforce!InstanceCreationException(_factoryParameters.instanceType, "Instance type is not defined, cannot create instance without knowing its type.");
|
||||||
return _factoryParameters.instanceType.create();
|
return _factoryParameters.instanceType.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
||||||
private shared DependencyContainer container;
|
private shared DependencyContainer container;
|
||||||
private bool isBeingInjected = false;
|
private bool isBeingInjected = false;
|
||||||
|
|
||||||
this(shared DependencyContainer container) {
|
this(shared DependencyContainer container) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createArgumentList(Params...)() {
|
private static string createArgumentList(Params...)() {
|
||||||
string argumentList = "";
|
string argumentList = "";
|
||||||
foreach(param; Params) {
|
foreach(param; Params) {
|
||||||
if (argumentList.length > 0) {
|
if (argumentList.length > 0) {
|
||||||
argumentList ~= ",";
|
argumentList ~= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
argumentList ~= "container.resolve!" ~ param.stringof;
|
argumentList ~= "container.resolve!" ~ param.stringof;
|
||||||
}
|
}
|
||||||
return argumentList;
|
return argumentList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createImportList(Params...)() {
|
private static string createImportList(Params...)() {
|
||||||
string importList = "";
|
string importList = "";
|
||||||
foreach(param; Params) {
|
foreach(param; Params) {
|
||||||
importList ~= createImportsString!param;
|
importList ~= createImportsString!param;
|
||||||
}
|
}
|
||||||
return importList;
|
return importList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool parametersAreValid(Params...)() {
|
private static bool parametersAreValid(Params...)() {
|
||||||
bool isValid = true;
|
bool isValid = true;
|
||||||
foreach(param; Params) {
|
foreach(param; Params) {
|
||||||
if (isBuiltinType!param) {
|
if (isBuiltinType!param) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Object createInstance() {
|
protected override Object createInstance() {
|
||||||
enforce!InstanceCreationException(container, "A dependency container is not defined. Cannot perform constructor injection without one.");
|
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));
|
enforce!InstanceCreationException(!isBeingInjected, format("%s is already being created and injected; possible circular dependencies in constructors?", InstanceType.stringof));
|
||||||
|
|
||||||
Object instance = null;
|
Object instance = null;
|
||||||
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
||||||
foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) {
|
foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) {
|
||||||
static if (parametersAreValid!(Parameters!ctor)) {
|
static if (parametersAreValid!(Parameters!ctor)) {
|
||||||
isBeingInjected = true;
|
isBeingInjected = true;
|
||||||
mixin(createImportsString!InstanceType
|
mixin(createImportsString!InstanceType
|
||||||
~ createImportList!(Parameters!ctor) ~ `
|
~ createImportList!(Parameters!ctor) ~ `
|
||||||
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `);
|
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `);
|
||||||
`);
|
`);
|
||||||
isBeingInjected = false;
|
isBeingInjected = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance is null) {
|
if (instance is null) {
|
||||||
instance = typeid(InstanceType).create();
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
module poodinis.imports;
|
||||||
|
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
public static string createImportsString(Type)() {
|
public static string createImportsString(Type)() {
|
||||||
string imports = `import ` ~ moduleName!Type ~ `;`;
|
string imports = `import ` ~ moduleName!Type ~ `;`;
|
||||||
static if (__traits(compiles, TemplateArgsOf!Type)) {
|
static if (__traits(compiles, TemplateArgsOf!Type)) {
|
||||||
foreach(TemplateArgType; TemplateArgsOf!Type) {
|
foreach(TemplateArgType; TemplateArgsOf!Type) {
|
||||||
static if (!isBuiltinType!TemplateArgType) {
|
static if (!isBuiltinType!TemplateArgType) {
|
||||||
imports ~= createImportsString!TemplateArgType;
|
imports ~= createImportsString!TemplateArgType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return imports;
|
return imports;
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* Kenji Hara,
|
* Kenji Hara,
|
||||||
* Shoichi Kato,
|
* Shoichi Kato,
|
||||||
* Mike Bierlee (m.bierlee@lostmoment.com)
|
* 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)
|
* License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -29,35 +29,35 @@ import std.exception;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
static if (!__traits(compiles, basicExceptionCtors)) {
|
static if (!__traits(compiles, basicExceptionCtors)) {
|
||||||
mixin template basicExceptionCtors()
|
mixin template basicExceptionCtors()
|
||||||
{
|
{
|
||||||
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @safe pure nothrow
|
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @safe pure nothrow
|
||||||
{
|
{
|
||||||
super(msg, file, line, next);
|
super(msg, file, line, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
|
this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
|
||||||
{
|
{
|
||||||
super(msg, file, line, next);
|
super(msg, file, line, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (!__traits(compiles, isFunction)) {
|
static if (!__traits(compiles, isFunction)) {
|
||||||
template isFunction(X...) if (X.length == 1)
|
template isFunction(X...) if (X.length == 1)
|
||||||
{
|
{
|
||||||
static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
|
static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
|
||||||
is(typeof(&X[0]) U == delegate))
|
is(typeof(&X[0]) U == delegate))
|
||||||
{
|
{
|
||||||
// x is a (nested) function symbol.
|
// x is a (nested) function symbol.
|
||||||
enum isFunction = true;
|
enum isFunction = true;
|
||||||
}
|
}
|
||||||
else static if (is(X[0] T))
|
else static if (is(X[0] T))
|
||||||
{
|
{
|
||||||
// x is a type. Take the type of it and examine.
|
// x is a type. Take the type of it and examine.
|
||||||
enum isFunction = is(T == function);
|
enum isFunction = is(T == function);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
enum isFunction = false;
|
enum isFunction = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
|
@ -17,61 +17,61 @@ import poodinis.container;
|
||||||
import poodinis.factory;
|
import poodinis.factory;
|
||||||
|
|
||||||
class Registration {
|
class Registration {
|
||||||
private TypeInfo _registeredType = null;
|
private TypeInfo _registeredType = null;
|
||||||
private TypeInfo_Class _instanceType = null;
|
private TypeInfo_Class _instanceType = null;
|
||||||
private Registration linkedRegistration;
|
private Registration linkedRegistration;
|
||||||
private shared(DependencyContainer) _originatingContainer;
|
private shared(DependencyContainer) _originatingContainer;
|
||||||
private InstanceFactory _instanceFactory;
|
private InstanceFactory _instanceFactory;
|
||||||
private void delegate() _preDestructor;
|
private void delegate() _preDestructor;
|
||||||
|
|
||||||
public @property registeredType() {
|
public @property registeredType() {
|
||||||
return _registeredType;
|
return _registeredType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property instanceType() {
|
public @property instanceType() {
|
||||||
return _instanceType;
|
return _instanceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property originatingContainer() {
|
public @property originatingContainer() {
|
||||||
return _originatingContainer;
|
return _originatingContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property instanceFactory() {
|
public @property instanceFactory() {
|
||||||
return _instanceFactory;
|
return _instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property preDestructor() {
|
public @property preDestructor() {
|
||||||
return _preDestructor;
|
return _preDestructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @property preDestructor(void delegate() preDestructor) {
|
protected @property preDestructor(void delegate() preDestructor) {
|
||||||
_preDestructor = preDestructor;
|
_preDestructor = preDestructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(TypeInfo registeredType, TypeInfo_Class instanceType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
|
this(TypeInfo registeredType, TypeInfo_Class instanceType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
|
||||||
this._registeredType = registeredType;
|
this._registeredType = registeredType;
|
||||||
this._instanceType = instanceType;
|
this._instanceType = instanceType;
|
||||||
this._originatingContainer = originatingContainer;
|
this._originatingContainer = originatingContainer;
|
||||||
this._instanceFactory = instanceFactory;
|
this._instanceFactory = instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInstance(InstantiationContext context = new InstantiationContext()) {
|
public Object getInstance(InstantiationContext context = new InstantiationContext()) {
|
||||||
if (linkedRegistration !is null) {
|
if (linkedRegistration !is null) {
|
||||||
return linkedRegistration.getInstance(context);
|
return linkedRegistration.getInstance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (instanceFactory is null) {
|
if (instanceFactory is null) {
|
||||||
throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString());
|
throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return instanceFactory.getInstance();
|
return instanceFactory.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Registration linkTo(Registration registration) {
|
public Registration linkTo(Registration registration) {
|
||||||
this.linkedRegistration = registration;
|
this.linkedRegistration = registration;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,35 +80,35 @@ class Registration {
|
||||||
* Effectively makes the given registration a singleton.
|
* Effectively makes the given registration a singleton.
|
||||||
*/
|
*/
|
||||||
public Registration singleInstance(Registration registration) {
|
public Registration singleInstance(Registration registration) {
|
||||||
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes);
|
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes);
|
||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scopes registrations to return a new instance every time the given registration is resolved.
|
* Scopes registrations to return a new instance every time the given registration is resolved.
|
||||||
*/
|
*/
|
||||||
public Registration newInstance(Registration registration) {
|
public Registration newInstance(Registration registration) {
|
||||||
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no);
|
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no);
|
||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scopes registrations to return the given instance every time the given registration is resolved.
|
* Scopes registrations to return the given instance every time the given registration is resolved.
|
||||||
*/
|
*/
|
||||||
public Registration existingInstance(Registration registration, Object instance) {
|
public Registration existingInstance(Registration registration, Object instance) {
|
||||||
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, instance);
|
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, instance);
|
||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string toConcreteTypeListString(Registration[] registrations) {
|
public string toConcreteTypeListString(Registration[] registrations) {
|
||||||
auto concreteTypeListString = "";
|
auto concreteTypeListString = "";
|
||||||
foreach (registration ; registrations) {
|
foreach (registration ; registrations) {
|
||||||
if (concreteTypeListString.length > 0) {
|
if (concreteTypeListString.length > 0) {
|
||||||
concreteTypeListString ~= ", ";
|
concreteTypeListString ~= ", ";
|
||||||
}
|
}
|
||||||
concreteTypeListString ~= registration.instanceType.toString();
|
concreteTypeListString ~= registration.instanceType.toString();
|
||||||
}
|
}
|
||||||
return concreteTypeListString;
|
return concreteTypeListString;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstantiationContext {}
|
class InstantiationContext {}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Mike Bierlee, m.bierlee@lostmoment.com
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
||||||
* Copyright: 2014-2017 Mike Bierlee
|
* Copyright: 2014-2018 Mike Bierlee
|
||||||
* License:
|
* License:
|
||||||
* This software is licensed under the terms of the MIT 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.
|
* 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.
|
* Thrown when something goes wrong during value injection.
|
||||||
*/
|
*/
|
||||||
class ValueInjectionException : Exception {
|
class ValueInjectionException : Exception {
|
||||||
mixin basicExceptionCtors;
|
mixin basicExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown by injectors when the value with the given key cannot be found.
|
* Thrown by injectors when the value with the given key cannot be found.
|
||||||
*/
|
*/
|
||||||
class ValueNotAvailableException : Exception {
|
class ValueNotAvailableException : Exception {
|
||||||
this(string key) {
|
this(string key) {
|
||||||
super(format("Value for key %s is not available", key));
|
super(format("Value for key %s is not available", key));
|
||||||
}
|
}
|
||||||
|
|
||||||
this(string key, Throwable cause) {
|
this(string key, Throwable cause) {
|
||||||
super(format("Value for key %s is not available", key), cause);
|
super(format("Value for key %s is not available", key), cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,12 +53,12 @@ class ValueNotAvailableException : Exception {
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
struct Value {
|
struct Value {
|
||||||
/**
|
/**
|
||||||
* The textual key used to find the value by injectors.
|
* The textual key used to find the value by injectors.
|
||||||
*
|
*
|
||||||
* The format is injector-specific.
|
* The format is injector-specific.
|
||||||
*/
|
*/
|
||||||
string key;
|
string key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,12 +79,12 @@ struct Value {
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
struct MandatoryValue {
|
struct MandatoryValue {
|
||||||
/**
|
/**
|
||||||
* The textual key used to find the value by injectors.
|
* The textual key used to find the value by injectors.
|
||||||
*
|
*
|
||||||
* The format is injector-specific.
|
* The format is injector-specific.
|
||||||
*/
|
*/
|
||||||
string key;
|
string key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,14 +110,14 @@ struct MandatoryValue {
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
interface ValueInjector(Type) {
|
interface ValueInjector(Type) {
|
||||||
/**
|
/**
|
||||||
* Get a value from the injector by key.
|
* Get a value from the injector by key.
|
||||||
*
|
*
|
||||||
* The key can have any format. Generally you are encouraged
|
* The key can have any format. Generally you are encouraged
|
||||||
* to accept a dot separated path, for example: server.http.port
|
* 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
|
* Throws: ValueNotAvailableException when the value for the given key is not available for any reason
|
||||||
*/
|
*/
|
||||||
Type get(string key);
|
Type get(string key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -12,171 +12,171 @@ import std.exception;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
|
|
||||||
// Test autowiring concrete type to existing instance
|
// Test autowiring concrete type to existing instance
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
auto componentB = new ComponentB();
|
auto componentB = new ComponentB();
|
||||||
container.autowire(componentB);
|
container.autowire(componentB);
|
||||||
assert(componentB !is null, "Autowirable dependency failed to autowire");
|
assert(componentB !is null, "Autowirable dependency failed to autowire");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring interface type to existing instance
|
// Test autowiring interface type to existing instance
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
container.autowire(componentD);
|
container.autowire(componentD);
|
||||||
assert(componentD.componentC !is null, "Autowirable dependency failed to autowire");
|
assert(componentD.componentC !is null, "Autowirable dependency failed to autowire");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring private members
|
// Test autowiring private members
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
container.autowire(componentD);
|
container.autowire(componentD);
|
||||||
assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed");
|
assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring will only happen once
|
// Test autowiring will only happen once
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC).newInstance();
|
container.register!(InterfaceA, ComponentC).newInstance();
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
container.autowire(componentD);
|
container.autowire(componentD);
|
||||||
auto expectedComponent = componentD.componentC;
|
auto expectedComponent = componentD.componentC;
|
||||||
container.autowire(componentD);
|
container.autowire(componentD);
|
||||||
auto actualComponent = componentD.componentC;
|
auto actualComponent = componentD.componentC;
|
||||||
assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance");
|
assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring unregistered type
|
// Test autowiring unregistered type
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
assertThrown!(ResolveException)(container.autowire(componentD), "Autowiring unregistered type should throw ResolveException");
|
assertThrown!(ResolveException)(container.autowire(componentD), "Autowiring unregistered type should throw ResolveException");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring member with non-autowire attribute does not autowire
|
// Test autowiring member with non-autowire attribute does not autowire
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto componentE = new ComponentE();
|
auto componentE = new ComponentE();
|
||||||
container.autowire(componentE);
|
container.autowire(componentE);
|
||||||
assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire");
|
assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire class with alias declaration
|
// Test autowire class with alias declaration
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
|
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
|
// Test autowire class with qualifier
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
auto componentX = container.resolve!(InterfaceA, ComponentX);
|
auto componentX = container.resolve!(InterfaceA, ComponentX);
|
||||||
|
|
||||||
auto monkeyShine = new MonkeyShine();
|
auto monkeyShine = new MonkeyShine();
|
||||||
container.autowire(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
|
// Test autowire class with multiple qualifiers
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
auto componentC = container.resolve!(InterfaceA, ComponentC);
|
auto componentC = container.resolve!(InterfaceA, ComponentC);
|
||||||
auto componentX = container.resolve!(InterfaceA, ComponentX);
|
auto componentX = container.resolve!(InterfaceA, ComponentX);
|
||||||
|
|
||||||
auto bootstrapBootstrap = new BootstrapBootstrap();
|
auto bootstrapBootstrap = new BootstrapBootstrap();
|
||||||
container.autowire(bootstrapBootstrap);
|
container.autowire(bootstrapBootstrap);
|
||||||
|
|
||||||
assert(bootstrapBootstrap.componentX is componentX, "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");
|
assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test getting instance from autowired registration will autowire instance
|
// Test getting instance from autowired registration will autowire instance
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
|
|
||||||
auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), new InstanceFactory(), container).singleInstance();
|
auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), new InstanceFactory(), container).singleInstance();
|
||||||
auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext());
|
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
|
// Test autowiring a dynamic array with all qualified types
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
|
|
||||||
auto lord = new LordOfTheComponents();
|
auto lord = new LordOfTheComponents();
|
||||||
container.autowire(lord);
|
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
|
// Test autowiring new instance of singleinstance registration with newInstance UDA
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
|
|
||||||
auto regularComponentA = container.resolve!ComponentA;
|
auto regularComponentA = container.resolve!ComponentA;
|
||||||
auto charlie = new ComponentCharlie();
|
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
|
// Test autowiring members from base class
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
container.register!ComponentB;
|
container.register!ComponentB;
|
||||||
container.register!ComponentZ;
|
container.register!ComponentZ;
|
||||||
|
|
||||||
auto instance = new ComponentZ();
|
auto instance = new ComponentZ();
|
||||||
container.autowire(instance);
|
container.autowire(instance);
|
||||||
|
|
||||||
assert(instance.componentA !is null);
|
assert(instance.componentA !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring optional dependencies
|
// Test autowiring optional dependencies
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto instance = new OuttaTime();
|
auto instance = new OuttaTime();
|
||||||
|
|
||||||
container.autowire(instance);
|
container.autowire(instance);
|
||||||
|
|
||||||
assert(instance.interfaceA is null);
|
assert(instance.interfaceA is null);
|
||||||
assert(instance.componentA is null);
|
assert(instance.componentA is null);
|
||||||
assert(instance.componentCs is null);
|
assert(instance.componentCs is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring class using value injection
|
// Test autowiring class using value injection
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
container.register!(ValueInjector!int, TestInjector);
|
container.register!(ValueInjector!int, TestInjector);
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
auto instance = new ValuedClass();
|
auto instance = new ValuedClass();
|
||||||
|
|
||||||
container.autowire(instance);
|
container.autowire(instance);
|
||||||
|
|
||||||
assert(instance.intValue == 8);
|
assert(instance.intValue == 8);
|
||||||
assert(instance.unrelated !is null);
|
assert(instance.unrelated !is null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -12,105 +12,105 @@ import std.exception;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
|
|
||||||
//Test register component registrations from context
|
//Test register component registrations from context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
auto bananaInstance = container.resolve!Banana;
|
auto bananaInstance = container.resolve!Banana;
|
||||||
|
|
||||||
assert(bananaInstance.color == "Yellow");
|
assert(bananaInstance.color == "Yellow");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test non-annotated methods are not registered
|
//Test non-annotated methods are not registered
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
assertThrown!ResolveException(container.resolve!Apple);
|
assertThrown!ResolveException(container.resolve!Apple);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register component by base type
|
//Test register component by base type
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
auto instance = container.resolve!Fruit;
|
auto instance = container.resolve!Fruit;
|
||||||
assert(instance.getShape() == "Pear shaped");
|
assert(instance.getShape() == "Pear shaped");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register components with multiple candidates
|
//Test register components with multiple candidates
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
|
||||||
auto rabbit = container.resolve!(Animal, Rabbit);
|
auto rabbit = container.resolve!(Animal, Rabbit);
|
||||||
assert(rabbit.getYell() == "Squeeeeeel");
|
assert(rabbit.getYell() == "Squeeeeeel");
|
||||||
|
|
||||||
auto wolf = container.resolve!(Animal, Wolf);
|
auto wolf = container.resolve!(Animal, Wolf);
|
||||||
assert(wolf.getYell() == "Wooooooooooo");
|
assert(wolf.getYell() == "Wooooooooooo");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register component as prototype
|
//Test register component as prototype
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
|
||||||
auto firstInstance = container.resolve!PieChart;
|
auto firstInstance = container.resolve!PieChart;
|
||||||
auto secondInstance = container.resolve!PieChart;
|
auto secondInstance = container.resolve!PieChart;
|
||||||
|
|
||||||
assert(firstInstance !is null && secondInstance !is null);
|
assert(firstInstance !is null && secondInstance !is null);
|
||||||
assert(firstInstance !is secondInstance);
|
assert(firstInstance !is secondInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test setting up simple dependencies through application context
|
// Test setting up simple dependencies through application context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!SimpleContext;
|
container.registerContext!SimpleContext;
|
||||||
auto instance = container.resolve!CakeChart;
|
auto instance = container.resolve!CakeChart;
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving dependency from registered application context
|
// Test resolving dependency from registered application context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!SimpleContext;
|
container.registerContext!SimpleContext;
|
||||||
auto instance = container.resolve!Apple;
|
auto instance = container.resolve!Apple;
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring application context
|
// Test autowiring application context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Apple;
|
container.register!Apple;
|
||||||
container.registerContext!AutowiredTestContext;
|
container.registerContext!AutowiredTestContext;
|
||||||
auto instance = container.resolve!ClassWrapper;
|
auto instance = container.resolve!ClassWrapper;
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.someClass !is null);
|
assert(instance.someClass !is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring application context with dependencies registered in same context
|
// Test autowiring application context with dependencies registered in same context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!ComplexAutowiredTestContext;
|
container.registerContext!ComplexAutowiredTestContext;
|
||||||
auto instance = container.resolve!ClassWrapperWrapper;
|
auto instance = container.resolve!ClassWrapperWrapper;
|
||||||
auto wrapper = container.resolve!ClassWrapper;
|
auto wrapper = container.resolve!ClassWrapper;
|
||||||
auto someClass = container.resolve!Apple;
|
auto someClass = container.resolve!Apple;
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.wrapper is wrapper);
|
assert(instance.wrapper is wrapper);
|
||||||
assert(instance.wrapper.someClass is someClass);
|
assert(instance.wrapper.someClass is someClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving registered context
|
// Test resolving registered context
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!TestContext;
|
container.registerContext!TestContext;
|
||||||
container.resolve!ApplicationContext;
|
container.resolve!ApplicationContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -12,137 +12,137 @@ import std.exception;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
|
|
||||||
// Test instance factory with singletons
|
// Test instance factory with singletons
|
||||||
unittest {
|
unittest {
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes);
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
assert(instanceOne !is null, "Created factory instance is null");
|
assert(instanceOne !is null, "Created factory instance is null");
|
||||||
assert(instanceOne is instanceTwo, "Created factory instance is not the same");
|
assert(instanceOne is instanceTwo, "Created factory instance is not the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test instance factory with new instances
|
// Test instance factory with new instances
|
||||||
unittest {
|
unittest {
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no);
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
assert(instanceOne !is null, "Created factory instance is null");
|
assert(instanceOne !is null, "Created factory instance is null");
|
||||||
assert(instanceOne !is instanceTwo, "Created factory instance is the same");
|
assert(instanceOne !is instanceTwo, "Created factory instance is the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test instance factory with existing instances
|
// Test instance factory with existing instances
|
||||||
unittest {
|
unittest {
|
||||||
auto existingInstance = new TestImplementation();
|
auto existingInstance = new TestImplementation();
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes, existingInstance);
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes, existingInstance);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
assert(instanceOne is existingInstance, "Created factory instance is not the existing instance");
|
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(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"
|
// Test instance factory with existing instances when setting singleton flag to "no"
|
||||||
unittest {
|
unittest {
|
||||||
auto existingInstance = new TestImplementation();
|
auto existingInstance = new TestImplementation();
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no, existingInstance);
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no, existingInstance);
|
||||||
auto instance = factory.getInstance();
|
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
|
// Test creating instance using custom factory method
|
||||||
unittest {
|
unittest {
|
||||||
Object factoryMethod() {
|
Object factoryMethod() {
|
||||||
auto instance = new TestImplementation();
|
auto instance = new TestImplementation();
|
||||||
instance.someContent = "Ducks!";
|
instance.someContent = "Ducks!";
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(null, CreatesSingleton.yes, null, &factoryMethod);
|
factory.factoryParameters = InstanceFactoryParameters(null, CreatesSingleton.yes, null, &factoryMethod);
|
||||||
auto instance = cast(TestImplementation) factory.getInstance();
|
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 !is null, "No instance was created by factory or could not be cast to expected type");
|
||||||
assert(instance.someContent == "Ducks!");
|
assert(instance.someContent == "Ducks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class
|
// Test injecting constructor of class
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructor(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructor(container);
|
||||||
auto instance = cast(ClassWithConstructor) factory.getInstance();
|
auto instance = cast(ClassWithConstructor) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.testImplementation is container.resolve!TestImplementation);
|
assert(instance.testImplementation is container.resolve!TestImplementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with multiple constructors injects the first candidate
|
// Test injecting constructor of class with multiple constructors injects the first candidate
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(container);
|
||||||
auto instance = cast(ClassWithMultipleConstructors) factory.getInstance();
|
auto instance = cast(ClassWithMultipleConstructors) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
||||||
assert(instance.testImplementation is null);
|
assert(instance.testImplementation is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with multiple constructor parameters
|
// Test injecting constructor of class with multiple constructor parameters
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(container);
|
||||||
auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance();
|
auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
||||||
assert(instance.testImplementation is container.resolve!TestImplementation);
|
assert(instance.testImplementation is container.resolve!TestImplementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with primitive constructor parameters
|
// Test injecting constructor of class with primitive constructor parameters
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(container);
|
||||||
auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance();
|
auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
assert(instance.someOtherClassThen is container.resolve!SomeOtherClassThen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Test injecting constructor of class with empty constructor will skip injection
|
// Test injecting constructor of class with empty constructor will skip injection
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container);
|
||||||
auto instance = cast(ClassWithEmptyConstructor) factory.getInstance();
|
auto instance = cast(ClassWithEmptyConstructor) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.someOtherClassThen is null);
|
assert(instance.someOtherClassThen is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with no candidates fails
|
// Test injecting constructor of class with no candidates fails
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -8,5 +8,5 @@
|
||||||
module poodinis.test.foreignDependencies;
|
module poodinis.test.foreignDependencies;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
class Ola {}
|
class Ola {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -12,51 +12,51 @@ import std.exception;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
|
|
||||||
// Test getting instance without scope defined throws exception
|
// Test getting instance without scope defined throws exception
|
||||||
unittest {
|
unittest {
|
||||||
Registration registration = new Registration(typeid(TestType), null, null, null);
|
Registration registration = new Registration(typeid(TestType), null, null, null);
|
||||||
assertThrown!(InstanceCreationException)(registration.getInstance(), null);
|
assertThrown!(InstanceCreationException)(registration.getInstance(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set single instance scope using scope setter
|
// Test set single instance scope using scope setter
|
||||||
unittest {
|
unittest {
|
||||||
Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null);
|
Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null);
|
||||||
auto chainedRegistration = registration.singleInstance();
|
auto chainedRegistration = registration.singleInstance();
|
||||||
auto instance1 = registration.getInstance();
|
auto instance1 = registration.getInstance();
|
||||||
auto instance2 = registration.getInstance();
|
auto instance2 = registration.getInstance();
|
||||||
assert(instance1 is instance2, "Registration with single instance scope did not return the same instance");
|
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");
|
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
|
// Test set new instance scope using scope setter
|
||||||
unittest {
|
unittest {
|
||||||
Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null);
|
Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null);
|
||||||
auto chainedRegistration = registration.newInstance();
|
auto chainedRegistration = registration.newInstance();
|
||||||
auto instance1 = registration.getInstance();
|
auto instance1 = registration.getInstance();
|
||||||
auto instance2 = registration.getInstance();
|
auto instance2 = registration.getInstance();
|
||||||
assert(instance1 !is instance2, "Registration with new instance scope did not return a different instance");
|
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");
|
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
|
// Test set existing instance scope using scope setter
|
||||||
unittest {
|
unittest {
|
||||||
Registration registration = new Registration(null, null, new InstanceFactory(), null);
|
Registration registration = new Registration(null, null, new InstanceFactory(), null);
|
||||||
auto expectedInstance = new TestType();
|
auto expectedInstance = new TestType();
|
||||||
auto chainedRegistration = registration.existingInstance(expectedInstance);
|
auto chainedRegistration = registration.existingInstance(expectedInstance);
|
||||||
auto actualInstance = registration.getInstance();
|
auto actualInstance = registration.getInstance();
|
||||||
assert(expectedInstance is expectedInstance, "Registration with existing instance scope did not return the same instance");
|
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");
|
assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test linking registrations
|
// Test linking registrations
|
||||||
unittest {
|
unittest {
|
||||||
Registration firstRegistration = new Registration(typeid(TestInterface), typeid(TestImplementation), new InstanceFactory(), null).singleInstance();
|
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);
|
Registration secondRegistration = new Registration(typeid(TestImplementation), typeid(TestImplementation), new InstanceFactory(), null).singleInstance().linkTo(firstRegistration);
|
||||||
|
|
||||||
auto firstInstance = firstRegistration.getInstance();
|
auto firstInstance = firstRegistration.getInstance();
|
||||||
auto secondInstance = secondRegistration.getInstance();
|
auto secondInstance = secondRegistration.getInstance();
|
||||||
|
|
||||||
assert(firstInstance is secondInstance);
|
assert(firstInstance is secondInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Poodinis Dependency Injection Framework
|
* 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.
|
* This software is licensed under the terms of the MIT license.
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@ -12,126 +12,126 @@ import std.exception;
|
||||||
|
|
||||||
version(unittest) {
|
version(unittest) {
|
||||||
|
|
||||||
struct LocalStruct {
|
struct LocalStruct {
|
||||||
bool wasInjected = false;
|
bool wasInjected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalStructInjector : ValueInjector!LocalStruct {
|
class LocalStructInjector : ValueInjector!LocalStruct {
|
||||||
public override LocalStruct get(string key) {
|
public override LocalStruct get(string key) {
|
||||||
auto data = LocalStruct(true);
|
auto data = LocalStruct(true);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalClassWithStruct {
|
class LocalClassWithStruct {
|
||||||
@Value("")
|
@Value("")
|
||||||
public LocalStruct localStruct;
|
public LocalStruct localStruct;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values
|
// Test injection of values
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!MyConfig;
|
container.register!MyConfig;
|
||||||
container.register!(ValueInjector!int, IntInjector);
|
container.register!(ValueInjector!int, IntInjector);
|
||||||
container.register!(ValueInjector!string, StringInjector);
|
container.register!(ValueInjector!string, StringInjector);
|
||||||
container.register!(ValueInjector!Thing, ThingInjector);
|
container.register!(ValueInjector!Thing, ThingInjector);
|
||||||
|
|
||||||
auto instance = container.resolve!MyConfig;
|
auto instance = container.resolve!MyConfig;
|
||||||
assert(instance.stuffs == 364);
|
assert(instance.stuffs == 364);
|
||||||
assert(instance.name == "Le Chef");
|
assert(instance.name == "Le Chef");
|
||||||
assert(instance.thing.x == 8899);
|
assert(instance.thing.x == 8899);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values throws exception when injector is not there
|
// Test injection of values throws exception when injector is not there
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!MyConfig;
|
container.register!MyConfig;
|
||||||
assertThrown!ResolveException(container.resolve!MyConfig);
|
assertThrown!ResolveException(container.resolve!MyConfig);
|
||||||
|
|
||||||
assertThrown!ValueInjectionException(autowire(container, new MyConfig()));
|
assertThrown!ValueInjectionException(autowire(container, new MyConfig()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values with defaults
|
// Test injection of values with defaults
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithDefaults;
|
container.register!ConfigWithDefaults;
|
||||||
container.register!(ValueInjector!int, DefaultIntInjector);
|
container.register!(ValueInjector!int, DefaultIntInjector);
|
||||||
|
|
||||||
auto instance = container.resolve!ConfigWithDefaults;
|
auto instance = container.resolve!ConfigWithDefaults;
|
||||||
assert(instance.noms == 9);
|
assert(instance.noms == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mandatory injection of values which are available
|
// Test mandatory injection of values which are available
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithMandatory;
|
container.register!ConfigWithMandatory;
|
||||||
container.register!(ValueInjector!int, MandatoryAvailableIntInjector);
|
container.register!(ValueInjector!int, MandatoryAvailableIntInjector);
|
||||||
|
|
||||||
auto instance = container.resolve!ConfigWithMandatory;
|
auto instance = container.resolve!ConfigWithMandatory;
|
||||||
assert(instance.nums == 7466);
|
assert(instance.nums == 7466);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mandatory injection of values which are not available
|
// Test mandatory injection of values which are not available
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithMandatory;
|
container.register!ConfigWithMandatory;
|
||||||
container.register!(ValueInjector!int, MandatoryUnavailableIntInjector);
|
container.register!(ValueInjector!int, MandatoryUnavailableIntInjector);
|
||||||
|
|
||||||
assertThrown!ResolveException(container.resolve!ConfigWithMandatory);
|
assertThrown!ResolveException(container.resolve!ConfigWithMandatory);
|
||||||
assertThrown!ValueInjectionException(autowire(container, new ConfigWithMandatory()));
|
assertThrown!ValueInjectionException(autowire(container, new ConfigWithMandatory()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting dependencies within value injectors
|
// Test injecting dependencies within value injectors
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto dependency = new Dependency();
|
auto dependency = new Dependency();
|
||||||
container.register!Dependency.existingInstance(dependency);
|
container.register!Dependency.existingInstance(dependency);
|
||||||
container.register!(ValueInjector!int, DependencyInjectedIntInjector);
|
container.register!(ValueInjector!int, DependencyInjectedIntInjector);
|
||||||
auto injector = cast(DependencyInjectedIntInjector) container.resolve!(ValueInjector!int);
|
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
|
// Test injecting circular dependencies within value injectors
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!int, CircularIntInjector);
|
container.register!(ValueInjector!int, CircularIntInjector);
|
||||||
auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int);
|
auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int);
|
||||||
|
|
||||||
assert(injector.dependency is injector);
|
assert(injector.dependency is injector);
|
||||||
assert(injector.get("whatever") == 3);
|
assert(injector.get("whatever") == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test value injection within value injectors
|
// Test value injection within value injectors
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!int, ValueInjectedIntInjector);
|
container.register!(ValueInjector!int, ValueInjectedIntInjector);
|
||||||
auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int);
|
auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int);
|
||||||
|
|
||||||
assert(injector.count == 5);
|
assert(injector.count == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test value injection within dependencies of value injectors
|
// Test value injection within dependencies of value injectors
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithDefaults;
|
container.register!ConfigWithDefaults;
|
||||||
|
|
||||||
container.register!(ValueInjector!int, DependencyValueInjectedIntInjector);
|
container.register!(ValueInjector!int, DependencyValueInjectedIntInjector);
|
||||||
auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(ValueInjector!int);
|
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)
|
// Test resolving locally defined struct injector (github issue #20)
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!LocalStruct, LocalStructInjector);
|
container.register!(ValueInjector!LocalStruct, LocalStructInjector);
|
||||||
container.register!LocalClassWithStruct;
|
container.register!LocalClassWithStruct;
|
||||||
|
|
||||||
auto injector = container.resolve!(ValueInjector!LocalStruct);
|
auto injector = container.resolve!(ValueInjector!LocalStruct);
|
||||||
assert(injector !is null);
|
assert(injector !is null);
|
||||||
|
|
||||||
auto localClass = container.resolve!LocalClassWithStruct;
|
auto localClass = container.resolve!LocalClassWithStruct;
|
||||||
assert(localClass.localStruct.wasInjected);
|
assert(localClass.localStruct.wasInjected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue