-
Notifications
You must be signed in to change notification settings - Fork 562
DIScope - an implementation of dependency injection container pattern #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -0,0 +1,333 @@ | |||
using System; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we move those to Utilities? They seem pretty boss room indepandant and would be great to reuse in future samples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely.
m_TypesToInstances[type] = instance; | ||
} | ||
|
||
public void BindAsSingle<TImplementation, TInterface>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason this has the same name as BindAsSingle with only one type?
Basically, this is a way to bind a default implementation for a given interface correct? Just "BindAsSingle" might be a bit confusing for that.
On another hand we don't want BindDefaultImplementationToInterfaceAsSingle...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, there is no specific reason to go with an overloaded function, however I just have a preference for overloads when they seem to make sense. So the intent here is to allow the user to bind a concrete implementation type that will be available by it's concrete type (that's a default of the DIScope - if something is bound, it is always automatically bound to (at the very least) it's concrete type) AND by the interface type.
I'll try and see if there are some better groupings and names for these method - lmk if you have ideas for short and concise intentful namings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BindInterfaceImplementationAsSingle seems like a mouthful too.
BindInterfaceAsSingle?
foreach (var component in components) InjectIn(component); | ||
} | ||
|
||
~DIScope() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
general formatting, usually you like having your destructor close to your constructor :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah crap, that's some automatic code cleanup that I did - that horrible foreach is also caused by the same... Or is it our actual codestyle? Anyhow - you're right - all of the creation/destruction logic belongs together.
e39a997
to
9520990
Compare
closing this PR - the content in here was merged with Lobby PR |
Description
This PR adds an implementation of a dependency injection container pattern (DIScope).
DIScope is only capable, for the sake of simplicity, of binding and resolving singletons.
The gist of DI is as follows: single responsibility principle, when applied to object instantiation, would suggest that if an object relies on the presence of certain dependencies, then finding those dependencies is outside the scope of instantiation itself. This gives us Dependency Injection Container - a class (With a special singleton reference to a Root scope) that will be responsible for providing dependencies, thus achieving a notion of Inversion of Control.
It effectively eliminates the need for singletons, allows to have more decoupled codebase that can be largely reliant on interface-based dependencies. DI also allows for easier testing of systems - we can easily swap out one implementation of an interface for another implementation and the only place where we'd need to touch the code is in the place where we declare dependencies and bind them to the DIScope.
So now we have this thing that is meant to provide dependencies, how do we author our code?
The code below showcases both the Binding stage (where we declare our dependencies which themselves can be interdependent on each-other) and an example of dependency injection and manual resolving:
And this is how we would provide the dependencies to the di scope:
Related Pull Requests
Issue Number(s) (*)
Fixes issue(s):
Manual testing scenarios
Questions or comments
Contribution checklist