Let’s now implement the Inversion of Control Principle: Don’t call us, we’ll call you.
In our specific project, it means that the Trainer class should not instantiate any dependency: LoudSpeaker
or QuietSpeaker
. It should only declare a dependency, and the actual class will be instantiated elsewhere and inserted into the Trainer class.
We’ll do this using dependency injection. Dependency injection is the actual insertion of the object. It can be done in a lot of ways, but we’ll focus on one type of dependency injection called constructor injection because it’s the most commonly used in the ASP.NET framework.
Here’s a common example, you might find inside IndexModel.cshtml.cs:
private static readonly ILogger _logger; public void IndexModel(ILogger logger) { _logger = logger; }
In this example, IndexModel
depends on some logging class. It declares its dependency in the form of an interface, ILogger
. It never instantiates an actual class though. Somewhere else in the code, a Logger
object is constructed and passed (or injected) into the IndexModel
:
IndexModel i = new IndexModel(new Logger());
(Some examples here don’t match the exact code you’d find in ASP.NET applications; they’ll be simplified so that we can focus on the subject of dependencies.)
Instructions
For this exercise, we changed the field’s name to _speaker
. This makes it easier to recognize as a private, internal field.
In Trainer.cs:
- Delete the body of the constructor
- Add an
ISpeaker
parameter to the constructor - In the constructor body, store the parameter value to the
_speaker
field
At this point, you’ll see some errors that we will soon fix.
In Program.cs, where we instantiate the Trainer
class, construct a new LoudSpeaker
object and pass it in as an argument to the Trainer
constructor.