Skip to content

Commit a0d31bc

Browse files
authored
Update ASP.NET Core fundamentals DI doc to highlight Blazor (#34418)
1 parent 726ca7c commit a0d31bc

File tree

1 file changed

+16
-37
lines changed

1 file changed

+16
-37
lines changed

aspnetcore/fundamentals/dependency-injection.md

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ By [Kirk Larkin](https://twitter.com/serpent5), [Steve Smith](https://ardalis.co
1717

1818
ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving [Inversion of Control (IoC)](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#dependency-inversion) between classes and their dependencies.
1919

20-
For more information specific to dependency injection within MVC controllers, see <xref:mvc/controllers/dependency-injection>.
20+
For Blazor DI guidance, which adds to or supersedes the guidance in this article, see <xref:blazor/fundamentals/dependency-injection>.
2121

22-
For information on using dependency injection in applications other than web apps, see [Dependency injection in .NET](/dotnet/core/extensions/dependency-injection).
22+
For information specific to dependency injection within MVC controllers, see <xref:mvc/controllers/dependency-injection>.
2323

24-
For more information on dependency injection of options, see <xref:fundamentals/configuration/options>.
24+
For information on using dependency injection in applications other than web apps, see [Dependency injection in .NET](/dotnet/core/extensions/dependency-injection).
2525

26-
This topic provides information on dependency injection in ASP.NET Core. The primary documentation on using dependency injection is contained in [Dependency injection in .NET](/dotnet/core/extensions/dependency-injection).
26+
For information on dependency injection of options, see <xref:fundamentals/configuration/options>.
2727

28-
For Blazor DI guidance, which adds to or supersedes the guidance in this article, see <xref:blazor/fundamentals/dependency-injection>.
28+
This article provides information on dependency injection in ASP.NET Core. The primary documentation on using dependency injection is contained in [Dependency injection in .NET](/dotnet/core/extensions/dependency-injection).
2929

3030
[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/dependency-injection/samples) ([how to download](xref:index#how-to-download-a-sample))
3131

@@ -59,7 +59,7 @@ This interface is implemented by a concrete type, `MyDependency`:
5959

6060
[!code-csharp[](~/fundamentals/dependency-injection/samples/6.x/DependencyInjectionSample/Services/MyDependency.cs?name=snippet1)]
6161

62-
The sample app registers the `IMyDependency` service with the concrete type `MyDependency`. The <xref:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped%2A> method registers the service with a scoped lifetime, the lifetime of a single request. [Service lifetimes](#service-lifetimes) are described later in this topic.
62+
The sample app registers the `IMyDependency` service with the concrete type `MyDependency`. The <xref:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped%2A> method registers the service with a scoped lifetime, the lifetime of a single request. [Service lifetimes](#service-lifetimes) are described later in this article.
6363

6464
[!code-csharp[](~/fundamentals/dependency-injection/samples/6.x/DependencyInjectionSample/Program.cs?name=snippet1)]
6565

@@ -89,13 +89,13 @@ The container resolves `ILogger<TCategoryName>` by taking advantage of [(generic
8989
In dependency injection terminology, a service:
9090

9191
* Is typically an object that provides a service to other objects, such as the `IMyDependency` service.
92-
* Is not related to a web service, although the service may use a web service.
92+
* Is not related to a web service, although the service might use a web service.
9393

9494
The framework provides a robust [logging](xref:fundamentals/logging/index) system. The `IMyDependency` implementations shown in the preceding examples were written to demonstrate basic DI, not to implement logging. Most apps shouldn't need to write loggers. The following code demonstrates using the default logging, which doesn't require any services to be registered:
9595

9696
[!code-csharp[](~/fundamentals/dependency-injection/samples/6.x/DependencyInjectionSample/Pages/About.cshtml.cs?name=snippet)]
9797

98-
Using the preceding code, there is no need to update `Program.cs`, because [logging](xref:fundamentals/logging/index) is provided by the framework.
98+
The preceding code works correctly without changing anything in `Program.cs`, because [logging](xref:fundamentals/logging/index) is provided by the framework.
9999

100100
## Register groups of services with extension methods
101101

@@ -124,9 +124,9 @@ See [Service registration methods](/dotnet/core/extensions/dependency-injection#
124124

125125
It's common to use multiple implementations when [mocking types for testing](xref:test/integration-tests#inject-mock-services).
126126

127-
Registering a service with only an implementation type is equivalent to registering that service with the same implementation and service type. This is why multiple implementations of a service cannot be registered using the methods that don't take an explicit service type. These methods can register multiple *instances* of a service, but they will all have the same *implementation* type.
127+
Registering a service with only an implementation type is equivalent to registering that service with the same implementation and service type. This is why multiple implementations of a service can't be registered using the methods that don't take an explicit service type. These methods can register multiple *instances* of a service, but they all have the same *implementation* type.
128128

129-
Any of the above service registration methods can be used to register multiple service instances of the same service type. In the following example, `AddSingleton` is called twice with `IMyDependency` as the service type. The second call to `AddSingleton` overrides the previous one when resolved as `IMyDependency` and adds to the previous one when multiple services are resolved via `IEnumerable<IMyDependency>`. Services appear in the order they were registered when resolved via `IEnumerable<{SERVICE}>`.
129+
Any of these service registration methods can be used to register multiple service instances of the same service type. In the following example, `AddSingleton` is called twice with `IMyDependency` as the service type. The second call to `AddSingleton` overrides the previous one when resolved as `IMyDependency` and adds to the previous one when multiple services are resolved via `IEnumerable<IMyDependency>`. Services appear in the order they were registered when resolved via `IEnumerable<{SERVICE}>`.
130130

131131
```csharp
132132
services.AddSingleton<IMyDependency, MyDependency>();
@@ -148,7 +148,7 @@ public class MyService
148148

149149
### Keyed services
150150

151-
*Keyed services* refers to a mechanism for registering and retrieving Dependency Injection (DI) services using keys. A service is associated with a key by calling <xref:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddKeyedSingleton%2A> (or `AddKeyedScoped` or `AddKeyedTransient`) to register it. Access a registered service by specifying the key with the [`[FromKeyedServices]`](xref:Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute) attribute. The following code shows how to use keyed services:
151+
The term *keyed services* refers to a mechanism for registering and retrieving Dependency Injection (DI) services using keys. A service is associated with a key by calling <xref:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddKeyedSingleton%2A> (or `AddKeyedScoped` or `AddKeyedTransient`) to register it. Access a registered service by specifying the key with the [`[FromKeyedServices]`](xref:Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute) attribute. The following code shows how to use keyed services:
152152

153153
:::code language="csharp" source="~/../AspNetCore.Docs.Samples/samples/KeyedServices9/Program.cs" highlight="6,7,12-14,39,47" id="snippet_1":::
154154

@@ -204,7 +204,7 @@ To reduce the logging output, set "Logging:LogLevel:Microsoft:Error" in the `app
204204

205205
[!code-json[](~/fundamentals/dependency-injection/samples/3.x/DependencyInjectionSample/appsettings.Development.json?highlight=7)]
206206

207-
## Resolve a service at app start up
207+
## Resolve a service at app startup
208208

209209
The following code shows how to resolve a scoped service for a limited duration when the app starts:
210210

@@ -233,7 +233,7 @@ When designing services for dependency injection:
233233
* Avoid direct instantiation of dependent classes within services. Direct instantiation couples the code to a particular implementation.
234234
* Make services small, well-factored, and easily tested.
235235

236-
If a class has a lot of injected dependencies, it might be a sign that the class has too many responsibilities and violates the [Single Responsibility Principle (SRP)](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#single-responsibility). Attempt to refactor the class by moving some of its responsibilities into new classes. Keep in mind that Razor Pages page model classes and MVC controller classes should focus on UI concerns.
236+
If a class has many injected dependencies, it might be a sign that the class has too many responsibilities and violates the [Single Responsibility Principle (SRP)](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#single-responsibility). Attempt to refactor the class by moving some of its responsibilities into new classes. Keep in mind that Razor Pages page model classes and MVC controller classes should focus on UI concerns.
237237

238238
### Disposal of services
239239

@@ -309,32 +309,11 @@ See [Recommendations](/dotnet/core/extensions/dependency-injection-guidelines#re
309309
* Another service locator variation to avoid is injecting a factory that resolves dependencies at runtime. Both of these practices mix [Inversion of Control](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#dependency-inversion) strategies.
310310
* Avoid static access to `HttpContext` (for example, [IHttpContextAccessor.HttpContext](xref:Microsoft.AspNetCore.Http.IHttpContextAccessor.HttpContext)).
311311

312-
<!--
313-
<a name="ASP0000"></a>
314-
* Avoid calls to <xref:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider%2A> in `ConfigureServices`. For example, consider the case where the `LoginPath` is loaded from configuration. Avoid the following approach:
315-
316-
![bad code calling BuildServiceProvider](~/fundamentals/dependency-injection/_static/badcodeX.png)
317-
318-
In the preceding image, selecting the green wavy line under `services.BuildServiceProvider` shows the following ASP0000 warning:
319-
320-
> ASP0000 Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.
321-
322-
Calling `BuildServiceProvider` creates a second container, which can create torn singletons and cause references to object graphs across multiple containers.
323-
324-
A correct way to get `LoginPath` is to use the options pattern's built-in support for DI:
325-
326-
[!code-csharp[](~/fundamentals/dependency-injection/samples/6.x/AntiPattern3/Program.cs?name=snippet)]
327-
328-
* Disposable transient services are captured by the container for disposal. This can turn into a memory leak if resolved from the top level container.
329-
* Enable scope validation to make sure the app doesn't have singletons that capture scoped services. For more information, see [Scope validation](#scope-validation).
330-
331-
Like all sets of recommendations, you may encounter situations where ignoring a recommendation is required. Exceptions are rare, mostly special cases within the framework itself.
332-
-->
333-
DI is an *alternative* to static/global object access patterns. You may not be able to realize the benefits of DI if you mix it with static object access.
312+
DI is an *alternative* to static/global object access patterns. You might not be able to realize the benefits of DI if you mix it with static object access.
334313

335314
## Recommended patterns for multi-tenancy in DI
336315

337-
[Orchard Core](https://github.com/OrchardCMS/OrchardCore) is an application framework for building modular, multi-tenant applications on ASP.NET Core. For more information, see the [Orchard Core Documentation](https://docs.orchardcore.net).
316+
[Orchard Core](https://github.com/OrchardCMS/OrchardCore) is an application framework for building modular, multitenant applications on ASP.NET Core. For more information, see the [Orchard Core Documentation](https://docs.orchardcore.net).
338317

339318
See the [Orchard Core samples](https://github.com/OrchardCMS/OrchardCore.Samples) for examples of how to build modular and multi-tenant apps using just the Orchard Core Framework without any of its CMS-specific features.
340319

@@ -363,10 +342,10 @@ The following table lists a small sample of these framework-registered services:
363342

364343
## Additional resources
365344

345+
* <xref:blazor/fundamentals/dependency-injection>
366346
* <xref:mvc/views/dependency-injection>
367347
* <xref:mvc/controllers/dependency-injection>
368348
* <xref:security/authorization/dependencyinjection>
369-
* <xref:blazor/fundamentals/dependency-injection>
370349
* [NDC Conference Patterns for DI app development](https://www.youtube.com/watch?v=x-C-CNBVTaY)
371350
* <xref:fundamentals/startup>
372351
* <xref:fundamentals/middleware/extensibility>

0 commit comments

Comments
 (0)