Decorator pattern using nested Injector - cannot achieve shared instance between nested scopes
See original GitHub issueHello,
I’m trying to have a shared instance of an object between a Decorator
and it’s decoree
- real world example would be to have a Transaction
object in a Repository
and f.e. TransactionalDecorator
which would open/close that transaction.
@proofit404 in one of the issues you’ve shown how decorators could be built using nested Injectors, the problem however is, that you’ve used objects in it (not classes or @value
- so no factory providers). I’m struggling to achieve a shared instance with classes.
Minimum viable example (note the comments):
from dependencies import Injector, this
class Connection:
pass
class Transaction:
def __init__(self, connection):
self.connection = connection
class Repository:
def __init__(self, transaction):
self.transaction = transaction
class Handler:
def __init__(self, repository, transaction):
self.repository = repository
self.transaction = transaction
class Decorator:
def __init__(self, decoree, transaction):
self.decoree = decoree
self.transaction = transaction
# pretty much resembles my usecase - `transaction` shall be shared between Decorator && Handler && Handler.repository
class DecoratorIoC(Injector):
handler = this.DecoratedHandler.handler
transaction = Transaction
repository = Repository
connection = Connection() # on purpose already an instance (in my usecase provided from outer-scope by Injector(**kwargs))
class DecoratedHandler(Injector):
handler = Decorator
decoree = this.Handler.handler
transaction = (this << 1).transaction
class Handler(Injector):
handler = Handler
repository = (this << 2).repository
transaction = (this << 1).transaction
decorator_handler = DecoratorIoC.handler
try:
assert decorator_handler.transaction is decorator_handler.decoree.transaction is decorator_handler.decoree.repository.transaction
except AssertionError:
pass
# a different approach, where dependencies are provided from the nested scope to the outer Injector instances
class NoOuterScopeDecoratorIoC(Injector):
handler = this.DecoratedHandler.handler
connection = Connection() # on purpose already an instance
class DecoratedHandler(Injector):
handler = Decorator
decoree = this.Handler.handler
transaction = this.Handler.transaction
class Handler(Injector):
handler = Handler
repository = Repository
transaction = Transaction
connection = (this << 2).connection
decorator_handler = NoOuterScopeDecoratorIoC.handler
try:
assert decorator_handler.transaction is decorator_handler.decoree.transaction is decorator_handler.decoree.repository.transaction
except AssertionError:
pass
# simplified example - just to show that one level of nesting is enough to not be able to achieve the expected (at least by me) behavior
class IoCSimple(Injector):
handler = this.Handler.handler
transaction = Transaction
repository = Repository
connection = Connection
class Handler(Injector):
handler = Handler
repository = (this << 1).repository
transaction = (this << 1).transaction
handler = IoCSimple.handler
try:
assert handler.transaction is handler.repository.transaction # throws
except AssertionError:
pass
# example just to show that without nesting it works
class DummyThis(Injector):
handler = Handler
connection = Connection
repository = Repository
transaction = this.transaction_aliased
transaction_aliased = Transaction
dummy_this = DummyThis.handler
assert dummy_this.transaction is dummy_this.repository.transaction
in before - I cannot use caching or singletons, because each built Handler should have its own Transaction object.
Any thoughts? Thanks in advance, and thanks for all your work @proofit404 !
Issue Analytics
- State:
- Created 2 years ago
- Comments:9 (7 by maintainers)
Top Results From Across the Web
Classes can't depend on nested injectors. · Issue #479 · proofit404 ...
Use this objects to point to specific dependencies inside nested injectors. ... Decorator pattern using nested Injector - cannot achieve shared instance ......
Read more >Dependency injection guidelines - .NET | Microsoft Learn
Learn various dependency injection guidelines and best practices for .NET application development.
Read more >Injection scopes | NestJS - A progressive Node.js framework
Hint Using singleton scope is recommended for most use cases. Sharing providers across consumers and across requests means that an instance can be...
Read more >Hierarchical injectors - Angular
Hierarchical dependency injection enables you to share dependencies between different parts of the application only when and if you need to.
Read more >c# - .NET Core IServiceScopeFactory.CreateScope() vs ...
In my case, the injection is for a IHostedService/BackgroundService which requires it's own scope separate from ASP.NET default. It would be ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The problem here is that each nested injector would create an independent injector subclass. Each time dependency resolver tries to access it’s attribute it will create an independent State object.
That’s a bug, can confirm.
Thanks for the report!
Fix on the way 🎉
Have a good day 🍸 🌴