From Dependency Injection, Principles, Practices, and Patterns
by Steven van Deursen and Mark Seemann

This articles explains the Scoped Lifestyle: what it is and when you might want to use it.

 

 


Take 37% off Dependency Injection, Principles, Practices, and Patterns. Just enter code fccseemann into the discount code box at checkout at manning.com.


As users of a web application, we’d like a response from the application as quickly as possible, even when other users are accessing the system at the same time. We don’t want our request to be put on a queue together with all the other users’ requests. We might have to wait an inordinate amount of time for a response if there are many requests ahead of ours. To address this issue, web applications handle requests concurrently.

Because of concurrency, Dependencies that aren’t thread-safe can’t be used as Singletons. On the other hand, using them as Transients can be inefficient or even downright problematic if you need to share a Dependency between different consumers within the same request.

This leads to the concept of a Scoped Lifestyle, where you decide to reuse instances within a given scope.

DEFINITION: Scoped Dependencies behave like Singleton Dependencies within a single, well-defined scope or request but aren’t shared across scopes. Each scope has its own cache of associated Dependencies.  

Figure 1 demonstrates how the Scoped Lifestyle works.

Figure 1 The Scoped Lifestyle indicates that you create, at most, one instance per specified scope

 

The Scoped Lifestyle makes sense for long-running applications that are tasked with processing operations that need to run with some degree of isolation. Isolation is required when these operations are processed in parallel, or when each operation contains its own state. Web applications are a great example of where the Scoped Lifestyle works well, because web applications typically process requests in parallel, and those requests typically contain some mutable state that’s specific to the request. But even if a web application starts some background operation that isn’t related to a web request, the Scoped Lifestyle is valuable. Even these background operations can typically be mapped to the concept of a request.

As with all Lifestyles, you can mix the Scoped Lifestyle with others so that, for example, some Dependencies are configured as Singletons, and others are shared per request.

Example: Composing a long-running application using a Scoped IUserContext

In this example, you’ll see how to compose a long-running web application, with Scoped IUserContext Dependency.

Listing 1  Resolving Scoped IUserContext instances

  
private HomeController CreateHomeController()
{
    IUserContext context = new AspNetUserContextAdapter(); ❶

    return
        new HomeController(
            new ProductService(
                new SqlProductRepository(this.connStr),
                context,                                   ❷
                new SqlUserRepository(
                    this.connStr,
                    context)));                            ❷
}
  

Create Scoped Dependency

Inject the Scoped Dependency into the Transient object graph

In this example, the CreateHomeController method acts as the application’s Composer. It creates a new object graph on every call. This call would typically be called once for every request for the application’s home page. During the call, however, the method creates only one instance of the AspNetUserContextAdapter. This AspNetUserContextAdapter instance is reused throughout the graph and injected in both the ProductService and the SqlUserRepository. That single AspNetUserContextAdapter is reused for the duration of the request, but other requests get their own instance.

Whereas a Transient Lifestyle implies that every consumer receives a private instance of a Dependency, a Scoped Lifestyle ensures that all consumers of all resolved graphs for that scope get the same instance.

That’s all for this article. If you want to learn more about the book, check it out on liveBook here.

You can also see other articles on common DI-related topics:

DI intro

Composition Root

Abstract Factories

Method Injection

Service Locator Anti-Pattern

Ambient Context Anti-Pattern

Constructor Injection

The Singleton Lifestyle

The Transient Lifestyle