Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
In this video, we'll learn about dependencies and how dependency injection can help to improve the manageability and testability of our code.
Using DI with Web API
If you'd to learn how to use DI with the ASP.NET Web API framework, check out this course on Web API:
Building Services with ASP.NET Web API
Project Files
If you'd like to follow along with this workshop, you can download the starting project files using this link:
http://treehouse-project-downloads.s3.amazonaws.com/dotnet-aspnet-di-solar-system.zip
Additional Learning
[MUSIC]
0:00
Hi, my name is James.
0:04
In this workshop, you'll learn
about dependency injection and
0:06
how to use it in
an ASP.NET MVC application.
0:11
We'll start with an overview
of what dependencies are, and
0:15
how dependency injection, or DI,
0:17
can help you to improve the manageability
and testability of your code.
0:20
We'll also see how to select, install, and
0:25
configure one of the popular DI
containers available for ASP.NET MVC.
0:28
And we'll finish up with a look at DI
in the ASP.NET Core web framework.
0:33
We won't be covering in
this workshop how to use
0:39
DI with the ASP.NET Web API framework.
0:42
That'll be covered in a future course
on Web API, see the teacher's notes for
0:45
more information.
0:49
Here's the project that we'll
be using in this workshop,
0:51
open in the community edition
of Visual Studio 2017.
0:54
Our project name is Treehouse.SolarSystem.
0:56
If you'd like to follow along,
see the teacher's notes for
1:01
a link to download the project files.
1:03
Our application is a very
basic ASP.NET MVC application.
1:05
We have a single controller
named PlanetsController,
1:10
and we have a single model named Planet.
1:15
We also have some entity framework
related classes in the Data folder.
1:19
We have a Context class,
a Database Initializer class,
1:24
that seeds our database with some data,
and a single Repository class.
1:29
Let's see what our application does.
1:34
And as you might expect, it displays
a list of the planets in our solar system,
1:37
all nine, I mean eight of them,
sorry Pluto.
1:41
Let's review how our application displays
the list of planets that you just saw.
1:45
Here's the index action method
that displays the list of planets.
1:49
We can see here that it's calling
a method called GetPlanets
1:53
on a repository private field.
1:57
The repository private field
is of type Repository, which
1:59
you can see in our class constructor,
we're instantiating an instance.
2:04
We're also instantiating an instance
of the Context class, and
2:08
passing that into
the repository's constructor.
2:11
The Repository class, GetPlanets method,
is using the Context class to query
2:17
the underlying database for
the list of planets.
2:22
Back in the controller, we can see that
we're also overriding the Dispose method,
2:26
which is being used to
dispose the _context
2:31
when our controller is being disposed.
2:34
We're doing this in order to control
the lifetime of our _context object.
2:36
So, what are dependencies?
2:41
As we just saw, our controller class,
well specifically the index action method,
2:43
is dependent upon an instance
of the repository class.
2:48
And, the repository class is dependent
upon an instance of the context class.
2:52
This chain of dependencies is
sometimes called a dependency tree or
2:59
a dependency graph.
3:03
The context and repository classes are
examples of database or data dependencies.
3:05
There are many other types of dependencies
that your application might have.
3:10
External dependencies,
like storage, messaging services,
3:15
like email or texting, or
any other restful service, or HTTP API.
3:19
Or maybe internal dependencies like
app settings, user authentication,
3:24
session management or really any business
logic that's specific to your application,
3:29
for instance, maybe a shopping card for
an e-commerce application.
3:35
Our controller shouldn't really be
concerned with instantiating instances
3:40
of its dependencies, or controlling
the lifetime of those dependencies.
3:44
Ideally, we should just be able to ask for
our dependencies.
3:49
One way to do that would be
to declare our dependencies
3:53
through constructor parameters.
3:56
Let's take a look at what
that would look like.
3:58
Let's add a parameter of type
Repository named repository.
4:01
Then, we can replace this instantiation of
the repository class with a reference to
4:08
that parameter.
4:13
We can also get rid of this
instantiation of the context class.
4:16
And, this boolean disposed private
field and the context private field.
4:21
Even more,
we can get rid of this dispose override.
4:28
That's a lot less code, isn't it?
4:36
With this approach, the underlying app
framework would provide our controller
4:39
with an instance of the repository class.
4:43
And for our repository class, it would
supply an instance of the context class.
4:48
And, it would also manage the live
time of the context for us.
4:54
This technique is known
as constructor injection.
4:58
Constructor injection is part
of a broader design pattern
5:01
known as dependency injection.
5:04
Dependency injection, or
5:07
DI, is related to the inversion of
control, or IOC design principle.
5:08
As we just saw in our example,
using DI classes, like our controller,
5:14
no longer need to concern themselves with
how their dependencies are instantiated.
5:19
In fact, any of our controller's
dependencies, like the repository class,
5:23
in turn might have their own dependencies.
5:27
That's no problem.
5:30
It's still not the concern
of our controller.
5:31
Directly instantiating
dependencies within a class,
5:34
tightly couples that class
to its dependencies.
5:37
Using DI helps us to create loosely
coupled classes or components.
5:40
Loose coupling improves code reusability,
5:44
making it easier to reuse our classes
in new ways or in new environments.
5:47
DI also helps to improve
the testability of our code.
5:53
For example, if we wanted to unit test
our controller's index action method,
5:56
we could provide the controller with
an instance of the repository class
6:01
that would avoid querying
the underlying database.
6:04
Instead, it'd simply return
a static collection of planets.
6:07
Supplying this mock repository
class to the controller class
6:11
would allow our unit test to run
in a performant predictable way.
6:16
Constructor injection isn't
the only way to implement DI.
6:20
Property injection and
6:23
method injection are two alternative
approaches that you can use.
6:25
We won't be covering these
approaches in this workshop,
6:28
as we'll be using constructor injection.
6:31
For more information about the IOC
design principle, property injection,
6:34
method injection, and an example of DI and
unit testing, see the teacher's notes.
6:38
Dependency injection is
a popular design pattern.
6:44
DI can be used with virtually any
language or platform, with or
6:47
without the support of
an external library.
6:50
Google's Angular framework and
Microsoft's ASP.NET Core web framework,
6:54
as we'll see later in this workshop,
provide built-in support for DI.
6:58
Unfortunately, the ASP.NET MVC web
framework doesn't provide support for
7:02
DI out of the box.
7:08
You need to install and
configure what's known as a DI container.
7:09
In the next video,
we'll learn about DI containers and
7:13
select a DI container library
to use in our project.
7:16
You need to sign up for Treehouse in order to download course files.
Sign up