Dependency Injection
-
Upload
alastair-smith -
Category
Technology
-
view
1.076 -
download
1
Transcript of Dependency Injection
DEPENDENCY INJECTIONPART 1
Alastair Smith (after Mark Seemann)
Agenda
Overview Concepts The Scope of Dependency Injection Patterns and Anti-Patterns
What is Dependency Injection?
What is Dependency Injection Not?
What Does Dependency Injection Buy You?
Overview
What is Dependency Injection? A technique A collection of patterns for loosely-
coupled code Favour composition over inheritance Program to the interface not the
implementation A form of Inversion of Control
What is Dependency Injection Not? Dependency Inversion (the D in
SOLID) You must first invert your dependencies
to properly apply dependency injection
Data Access Layer
Business Logic Layer
Presentation Layer
What Does DI Buy You?
Testable and maintainable code Encourages SOLID code
Late binding Swapping services out for other
implementations Easy extensibility
Code can be extended in ways not originally envisaged
The Purpose of DI
What to Inject (and What Not to Inject)
Concepts
Tight Coupling
Wall
How do we decouple?
Wall
How do we get new functionality?
Wall
UPS
How do we do multiple things?
Wall
UPS
How do we use an incompatible device?
Wall
UPS
Design Patterns will only get you so far How you assemble your bricks
matters
What to Inject
VOLATILE DEPENDENCIESlibraries that: introduce the need to configure an
external environment are still in development aren’t installed on all machines in the
development organisation E.g.: EntityBroker, Phoenix,
SpreadsheetGear Inject across SEAMS
What Not to Inject
STABLE DEPENDENCIESlibraries or frameworks that: won’t introduce breaking changes with
new versions you never expect to have to replace
E.g.: the BCL
Object Composition
Lifetime Management
Interception
The Scope of Dependency Injection
Object Composition
Building object graphs into functional units Creating objects Creating relationships between objects
No more new Foo() Single Responsibility Principle Regain control through a DI container
Provides late-binding, extensibility and parallel development benefits
Lifetime Management
Must invert control of an object’s lifetime management as well as the dependency itself
Different lifetime options Singleton Per-request Per-thread (and others)
A Word on IDisposable
Complicated by use of Dependency Injection
Do not mark your abstractions as IDisposable
Let the DI Container handle disposable implementations
Hide Ephemeral Disposables behind a SEAM Use an injected Abstract Factory to
create them Keep their using blocks short
Interception
Applying functionality on the fly Used to add Cross-Cutting Concerns:
Logging Auditing Performance Access control Security ...
Aspect-Oriented Programming Cross-Cutting Concerns applied via
attributes decorating a method [PrincipalPermission] [HandleError]
Requires either: Post-compilation step (e.g., PostSharp),
or A custom host (e.g., WCF, ASP.NET MVC,
NUnit)
AOP Disadvantages
Attributes are compiled with the code they adorn Can’t easily change behaviour
Limited options for applying attributes
Attributes must have a simple constructor Makes lifetime management trickier
Dynamic Interception
Can be achieved with liberal use of Decorators Violates DRY Lots of boilerplate code
Container-level feature Castle Windsor, Spring.NET, Unity and
Ninject all support it Neat way to achieve DRY and SOLID
code
Constructor Injection
Property Injection
Method Injection
Ambient Context
Patterns
Terminology
COMPOSITION ROOT Where the application is assembled
DEPENDENCY A Volatile Dependency from Part 1
DEFAULT value E.g. a no-op, such as a Null Object Not your default implementation!
Constructor Injection
This should be your default choice for DI
Guarantees that a necessary DEPENDENCY is always available to the class
Advantages Disadvantages
Injection guaranteed Some frameworks make it difficult
Easy to implement
Property Injection
Use when a DEPENDENCY is optional
There should be a good LOCAL DEFAULT
Advantages Disadvantages
Easy to understand Limited applicability
Not entirely simple to implement robustly
Method Injection
Use when a DEPENDENCY varies per call of a method
Usually the DEPENDENCY represents some context for the method call
Limited applicability
Advantages Disadvantages
Allows the caller to provide operation-specific context
Limited applicability
Ambient Context
Use to inject static DEPENDENCIES Only use when querying the
dependency A proper LOCAL DEFAULT exists It must be guaranteed available
Advantages Disadvantages
Doesn’t pollute APIs Implicit
Is always available Hard to implement correctly
May not work well in some runtimes
Control Freak
Bastard Injection
Service Locator
Constrained Construction
Anti-Patterns
Control Freak
DEPENDENCIES are controlled directly E.g., creating an instance of Foo for a
field of type IFoo. Usually occurs within a Factory Root these out of your codebase! Refactor to Constructor Injection
Bastard Injection
Foreign DEFAULTS are used as default values for DEPENDENCIES E.g., AccountController in ASP.NET
MVC Refactor towards Constructor
Injection Refactor towards Property Injection
But only if there’s a LOCAL DEFAULT
Service Locator
Calling into your IoC container outside of the COMPOSITION ROOT
Can tightly-couple your application to your IoC container!
Acts as a replacement for new Foo() Refactor towards Constructor
Injection
Constrained Construction
Constructors are assumed to have a particular signature E.g., WebForms requires Pages to have a
default constructor No easy refactoring to DI
Some possibilities via Abstract Factory
Any questions?
End of Part One
DEPENDENCY INJECTIONPART 2
Alastair Smith (after Mark Seemann)
ASP.NET MVC
WPF
WCF
ASP.NET
Manually Composing Applications
ASP.NET MVC
COMPOSITION ROOT: global.asax + IControllerFactory Can also use WebActivator package from
NuGet Ignore IDependencyResolver!
Intended to be a Service Locator Removes ability to manage object
lifetime IControllerFactory is the
appropriate extensibility point Use Constructor Injection on your
Controllers
WPF with MVVM
COMPOSITION ROOT: Application.OnStartup()
Use Constructor Injection on your MainWindowViewModel
Create an IWindow interface and inject this Implemented by a MainWindowAdapter for each
Window Create a MainWindowViewModelFactory
Needed because there is a circular dependency between the View and the ViewModel
WCF
COMPOSITION ROOT: triplet of ServiceHostFactory ServiceHost IInstanceProvider
ASP.NET
Suffers from Constrained Construction
COMPOSITION ROOT: each Page class Single Responsibility Principle
Model-View-Presenter (MVP) Keep Presenters fully independent of System.Web
Any questions?
End of Part Two