Dependency Injection Principles, Practices, and Patterns
Steven van Deursen and Mark Seemann
  • March 2019
  • ISBN 9781617294730
  • 552 pages
  • printed in black & white
free previous edition included
An eBook copy of the previous edition of this book is included at no additional cost. It will be automatically added to your Manning Bookshelf within 24 hours of purchase.

Actually three books in one: a really good introduction to DI in .NET, an even better one to DI in general, and an absolutely excellent introduction to OO principles and software design.

Mikkel Arentoft, Danske Bank
Dependency Injection Principles, Practices, and Patterns teaches you to use DI 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

Chapter 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

Summary

Chapter 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 missing composability

2.3.1 Dependency graph analysis

2.3.2 Data access interface analysis

2.3.3 Miscellaneous other issues

2.4 Conclusion

Summary

Chapter 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

Summary

Part 2: Catalog

Chapter 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.4 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 Wrap-up

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 ProductEntity

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

Summary

Chapter 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

Summary

Chapter 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

Summary

Part 3: Pure DI

Chapter 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 UpdateCurrency’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

Summary

Chapter 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 The Singleton Lifestyle

8.3.2 The Transient Lifestyle

8.3.3 The Scoped Lifestyle

8.4 Bad Lifestyle choices

8.4.1 Captive Dependencies

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

Summary

Chapter 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 using the Decorator pattern

9.2.3 Preventing unauthorized access to sensitive functionality using a Decorator

Summary

Chapter 10: Aspect-Oriented Programming by design

10.1 Introducing AOP

10.2 The 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 design by applying SOLID principles

10.3.4 Adding more Cross-Cutting Concerns

10.3.5 Conclusion

Summary

Chapter 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

Summary

Part 4: DI Containers

Chapter 12: DI Container introduction

12.1 Introducing DI Containers

12.1.1 Exploring 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

Summary

Chapter 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

Summary

Chapter 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

Summary

Chapter 15: The Microsoft.Extensions.DependencyInjection DI Container

15.1 Introducing Microsoft.Extensions.DependencyInjection

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

Summary

About the Technology

Dependency Injection (DI) is a great way to reduce tight coupling between software components. Instead of hard-coding dependencies, such as specifying a database driver, you make those connections through a third party. Central to application frameworks like ASP.NET Core, DI enables you to better manage changes and other complexity in your software.

About the book

Dependency Injection Principles, Practices, and Patterns is a revised and expanded edition of the bestselling classic Dependency Injection in .NET. It teaches you DI from the ground up, featuring relevant examples, patterns, and anti-patterns for creating loosely coupled, well-structured applications. The well-annotated code and diagrams use C# examples to illustrate principles that work flawlessly with modern object-oriented languages and DI libraries.

What's inside

  • Refactoring existing code into loosely coupled code
  • DI techniques that work with statically typed OO languages
  • Integration with common .NET frameworks
  • Updated examples illustrating DI in .NET Core

About the reader

For intermediate OO developers.

About the authors

Mark Seemann is a programmer, software architect, and speaker who has been working with software since 1995, including six years with Microsoft. Steven van Deursen is a seasoned .NET developer and architect, and the author and maintainer of the Simple Injector DI library.

combo $59.99 pBook + eBook + liveBook
includes previous edition
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