Dependency Injection Principles, Practices, and Patterns
Steven van Deursen and Mark Seemann
  • MEAP began April 2017
  • Publication in March 2019 (estimated)
  • ISBN 9781617294730
  • 552 pages (estimated)
  • printed in black & white
free previous edition included

I wish I had this book when I was learning the subject.

Cemre Mengu

Dependency Injection Principles, Practices, and Patterns teaches you to use Dependency Injection to reduce hard-coded dependencies between application components. You'll start by learning what DI is and what types of applications will benefit from it. Then, you'll work through concrete scenarios using C# and the .NET framework to implement DI in your own projects. As you dive into the thoroughly-explained examples, you'll develop a foundation you can apply to any of the many DI libraries for .NET and .NET Core.

Table of Contents detailed table of contents

Part 1: Putting Dependency Injection on the map

1 The basics of Dependency Injection: what, why, and how

1.1 Writing maintainable code

1.1.1 Common myths about DI

1.1.2 Understanding the purpose of DI

1.2 A simple example: Hello DI!

1.2.1 Hello DI! code

1.2.2 Benefits of DI

1.3 What to inject and what not to inject

1.3.1 Stable Dependencies

1.3.2 Volatile Dependencies

1.4 DI scope

1.4.1 Object Composition

1.4.2 Object Lifetime

1.4.3 Interception

1.4.4 DI in three dimensions

1.5 Conclusion

1.6 Summary

2 Writing tightly coupled code

2.1 Building a tightly coupled application

2.1.1 Meet Mary Rowan

2.1.2 Creating the data layer

2.1.3 Creating the domain layer

2.1.4 Creating the UI layer

2.2 Evaluating the tightly coupled application

2.2.1 Evaluating the dependency graph

2.2.2 Evaluating composability

2.3 Analysis of the missing composability

2.3.1 Dependency graph analysis

2.3.2 Data access interface analysis

2.3.3 Miscellaneous other issues

2.4 Conclusion

2.5 Summary

3 Writing loosely coupled code

3.1 Rebuilding the e-commerce application

3.1.1 Building a more maintainable UI

3.1.2 Building an independent domain model

3.1.3 Building a new data access layer

3.1.4 Implementing an ASP.NET Core-specific IUserContext Adapter

3.1.5 Composing the application in the Composition Root

3.2 Analyzing the loosely coupled implementation

3.2.1 Understanding the interaction between components

3.2.2 Analyzing the new dependency graph

3.3 Summary

Part 2: Catalog

4 DI patterns

4.1 Composition Root

4.1.1 How Composition Root works

4.1.2 Using a DI Container in a Composition Root

4.1.3 Example: implementing a Composition Root using Pure DI

4.1.2 The apparent dependency explosion

4.2 Constructor Injection

4.2.1 How Constructor Injection works

4.2.2 When to use Constructor Injection

4.2.3 Known use of Constructor Injection

4.2.5 Summary

4.3 Method Injection

4.3.1 How Method Injection works

4.3.2 When to use Method Injection

4.3.3 Known use of Method Injection

4.3.4 Example: adding currency conversions to the Product Entity

4.4 Property Injection

4.4.1 How Property Injection works

4.4.2 When to use Property Injection

4.4.3 Known uses of Property Injection

4.4.4 Example: Property Injection as an extensibility model of a reusable library

4.5 Choosing which pattern to use

4.6 Summary

5 DI anti-patterns

5.1 Control Freak

5.1.1 Example: Control Freak through newing up Dependencies

5.1.2 Example: Control Freak through factories

5.1.3 Example: Control Freak through overloaded constructors

5.1.4 Analysis of Control Freak

5.2 Service Locator

5.2.1 Example: ProductService using a Service Locator

5.2.2 Analysis of Service Locator

5.3 Ambient Context

5.3.1 Example: Accessing time through Ambient Context

5.3.2 Example: Logging through Ambient Context

5.3.3 Analysis of Ambient Context

5.4 Constrained Construction

5.4.1 Example: late-binding a ProductRepository

5.4.2 Analysis of Constrained Construction

5.5 Summary

6 Code smells

6.1 Dealing with the Constructor Over-injection code smell

6.1.1 Recognizing Constructor Over-injection

6.1.2 Refactoring from Constructor Over-injection to Facade Services

6.1.3 Refactoring from Constructor Over-injection to domain events

6.2 Abuse of Abstract Factories

6.2.1 Abusing Abstract Factories to overcome lifetime problems

6.2.2 Abusing Abstract Factories to select Dependencies based on runtime data

6.3 Fixing cyclic Dependencies

6.3.1 Example: Dependency cycle caused by an SRP violation

6.3.2 Analysis of Mary’s Dependency cycle

6.3.3 Refactoring from SRP violations to resolve the Dependency cycle

6.3.4 Common strategies for breaking Dependency cycles

6.3.5 Last resort: breaking the cycle with Property Injection

6.4 Summary

Part 3: Pure DI

7 Application composition

7.1 Composing console applications

7.1.1 Example: updating currencies using the UpdateCurrency program

7.1.2 Building the Composition Root of the UpdateCurrency program

7.1.3 Composing object graphs in CreateCurrencyParser

7.1.4 A closer look at the UpdateCurrency program’s layering

7.2 Composing UWP applications

7.2.1 UWP composition

7.2.2 Example: wiring up a product-management rich client

7.2.3 Implementing the Composition Root in the UWP application

7.3 Composing ASP.NET Core MVC applications

7.3.1 Creating a custom controller activator

7.3.2 Constructing custom middleware components using Pure DI

7.4 Summary

8 Object lifetime

8.1 Managing Dependency Lifetime

8.1.1 Introducing Lifetime Management

8.1.2 Managing lifetime with Pure DI

8.2 Working with disposable Dependencies

8.2.1 Consuming disposable Dependencies

8.2.2 Managing disposable Dependencies

8.3 Lifestyle catalog

8.3.1 Using the Singleton Lifestyle to reuse instances for the lifetime of a Composer

8.3.2 Using the Transient Lifestyle to return a new instance on every request

8.3.3 Using the Scoped Lifestyle to share instances within a single well-defined scope

8.4 Bad Lifestyle choices

8.4.1 Captive Dependencies: keeping Dependencies referenced beyond their expected lifetime

8.4.2 Using Leaky Abstractions to leak Lifestyle choices to consumers

8.4.3 Causing concurrency bugs by tying instances to the lifetime of a thread

8.5 Summary

9 Interception

9.1 Introducing Interception

9.1.1 Decorator design pattern

9.1.2 Example: implementing auditing using a Decorator

9.2 Implementing Cross-Cutting Concerns

9.2.1 Intercepting with a Circuit Breaker

9.2.2 Reporting exceptions to the user using the Decorator pattern

9.2.3 Preventing unauthorized access to sensitive functionality using a Decorator

9.3 Summary

10 Aspect-Oriented Programming by design

10.1 Introducing AOP

10.2 SOLID principles

10.2.1 Single Responsibility Principle (SRP)

10.2.2 Open/Closed Principle (OCP)

10.2.3 Liskov Substitution Principle (LSP)

10.2.4 Interface Segregation Principle (ISP)

10.2.5 Dependency Inversion Principle (DIP)

10.2.6 SOLID principles and Interception

10.3 SOLID as a driver for AOP

10.3.2 Analysis of IProductService from the perspective of SOLID

10.3.3 Improving the design by applying SOLID principles step-by-step

10.3.4 Adding more Cross-Cutting Concerns

10.3.5 Conclusion

10.4 Summary

11 Tool-based Aspect-Oriented Programming

11.1 Dynamic Interception

11.1.1 Example: Interception with Castle Dynamic Proxy

11.1.2 Analysis of dynamic Interception

11.2 Compile-time weaving

11.2.1 Example: applying a transaction aspect using compile-time weaving

11.2.2 Analysis of compile-time weaving

11.3 Summary

Part 4: DI Containers

12 DI Container introduction

12.1 Introducing DI Containers

12.1.1 Exploring the containers' Resolve API

12.1.2 Auto-Wiring

12.1.3 Example: Implementing a simplistic DI Container that supports Auto-Wiring

12.2 Configuring DI Containers

12.2.1 Configuring containers with configuration files

12.2.2 Configuring containers using Configuration as Code

12.2.3 Configuring containers by convention using Auto-Registration

12.2.4 Mixing and matching configuration approaches

12.3 When to use a DI Container

12.3.1 Using third-party libraries involves costs and risks

12.3.2 Pure DI gives a shorter feedback cycle

12.3.3 The verdict: when to use a DI Container

12.4 Summary

13 The Autofac DI Container

13.1 Introducing Autofac

13.1.1 Resolving objects

13.1.2 Configuring the ContainerBuilder

13.2 Managing lifetime

13.2.1 Configuring instance scopes

13.2.2 Releasing components

13.3 Registering difficult APIs

13.3.1 Configuring primitive Dependencies

13.3.2 Registering objects with code blocks

13.4 Working with multiple components

13.4.1 Selecting among multiple candidates

13.4.2 Wiring sequences

13.4.3 Wiring Decorators

13.4.4 Wiring Composites

13.5 Summary

14 The Simple Injector DI Container

14.1 Introducing Simple Injector

14.1.1 Resolving objects

14.1.2 Configuring the Container

14.2 Managing lifetime

14.2.1 Configuring Lifestyles

14.2.2 Releasing components

14.2.3 Ambient scopes

14.2.4 Diagnosing the container for common lifetime problems

14.3 Registering difficult APIs

14.3.1 Configuring primitive Dependencies

14.3.2 Extracting primitive Dependencies to Parameter Objects

14.3.3 Registering objects with code blocks

14.4 Working with multiple components

14.4.1 Selecting among multiple candidates

14.4.2 Wiring sequences

14.4.3 Wiring Decorators

14.4.4 Wiring Composites

14.4.5 Sequences are streams

14.5 Summary

15 The Microsoft.Extensions.DependencyInjection DI Container

15.1 Introducing Microsoft.Extensions.DependencyInjection (MS.DI)

15.1.1 Resolving objects

15.1.2 Configuring the ServiceCollection

15.2 Managing lifetime

15.2.1 Configuring Lifestyles

15.2.2 Releasing components

15.3 Registering difficult APIs

15.3.1 Configuring primitive Dependencies

15.3.2 Extracting primitive Dependencies to Parameter Objects

15.3.3 Registering objects with code blocks

15.4 Working with multiple components

15.4.1 Selecting among multiple candidates

15.4.2 Wiring sequences

15.4.3 Wiring Decorators

15.4.4 Wiring Composites

15.5 Summary

About the Technology

Dependency Injection is an application design pattern where components are loosely-coupled with the objects or data on which they have a dependency. The dependent component broadcasts its need, and an external service composes the objects, or "injects" the "dependency". This basic pattern allows objects to work together without being bound into rigid, pre-defined architectures and communication. Dependency Injection has become one of the most dominant practices in the past decade, and it's now required knowledge for .NET developers.

What's inside

  • DI patterns and anti-patterns
  • Aspect-oriented programming
  • Integration with common .NET application frameworks
  • Using Microsoft and open source DI libraries and containers

About the reader

This book is written for intermediate .NET developers and beyond. No previous experience with DI or DI libraries is required.

About the authors

.NET legend Mark Seemann has teamed up with developer and architect Steven van Deursen in revising and updating this classic book originally written by Mark. Steven is the author and maintainer of a popular DI library for .NET called Simple Injector and is an active voice in the Dependency Injection community. Mark Seemann remains a regular speaker at international software development conferences.

Manning Early Access Program (MEAP) Read chapters as they are written, get the finished eBook as soon as it’s ready, and receive the pBook long before it's in bookstores.
MEAP combo $59.99 pBook + eBook + liveBook
includes previous edition
MEAP eBook $47.99 pdf + ePub + kindle + liveBook
includes previous edition

placing your order...

Don't refresh or navigate away from the page.

FREE domestic shipping on three or more pBooks

This must be the deepest and clearest explanation about what Dependency Injection is and is not, how it works, and how it should be applied.

Sergio Romero

This book is a masterpiece. It's amazing, it's fundamental for every software developer that wants to write solid and correct code. This should be read by all developers, not only the ones working on .NET.

Emanuele Origgi