# 六、依赖注入/控制反转

## 依赖注入（IOC）

通俗来说，就是把有依赖关系的类放到容器中，然后在我们需要这些类时，容器自动解析出这些类的实例，这就是依赖注入。也就是程序员无需自己创建一个服务对象类，而是将该服务对象类以某种锲约（通常时接口）配置到容器中，然后容器根据这些锲约定位到对象类并创建出来。

依赖注入最大的好处时实现类的解耦，利于程序拓展、单元测试、自动化模拟测试等。

## 控制反转（DI）

控制反转只是一个概念，也就是将创建对象实例的控制权（原本是程序员）从代码控制权剥离到 IOC容器中控制。也就是上面 依赖注入（IOC）创建对象的过程描述。

要想接口实现构造函数注入方式创建对象，则实例类需继承或间接继承 `ITransientDependency` 接口，如：

## 应用场景

在现代化的应用程序中，依赖注入/控制反转已经成为框架底层不可或缺的组件/模式，这种模式最显著的应用就是**面向接口编程**，所有的服务/类都必须抽象出接口规范，并且所有的服务/类之间的调用都是通过接口调用。

默认情况下，所有的服务/类需要调用第三方或自定义的服务/类都是通过实例类构造函数进行申明注入的。

**IOC容器会托管我们所有注册的服务/类，在这个服务/类被创建的时候，会扫描构造函数的参数，并动态创建这些依赖服务/类对象并赋值给页面私有只读变量中。**

如下面代码：

```csharp
using System;

namespace Hoa.Application.SomeModule
{
    public class SomeAppService : ISomeAppService, ITransientDependency // 继承 ITransientDependency 接口
    {
    }
}
```

`AuthorizationAppService` 构造函数中申明了 `ISomeAppService` 接口，这时，当 `IAuthorizationAppService` 接口被调用时，会自动注入 ``ISomeAppService` 接口实例。``

```csharp
using System;

namespace Hoa.Application.Authorization
{
    public class AuthorizationAppService : IAuthorizationAppService, IAppServiceDependency
    {
        // 构造函数注入
        private readonly ISomeAppService _someService;
        public AuthorizationAppService(ISomeAppService someService)
        {
            _someService_ = someService;
        }
    }
}
```

## 框架内置依赖注入契约

### 简易方式

在 Hoa Framework 框架中，提供一种更加建议的契约方式，只需要接口的**实现类直接或间接继承 `ITransientDependency` 或 `IScopeDependency`**&#x5373;可。

### 强大的 [Autofac](https://autofac.readthedocs.io/) 配置契约

Hoa Framework 框架默认继承了 `Autofac` 依赖注入/控制反转组件，需手动配置锲约只需要在 各个项目层根目录下带 `项目层名称Module.cs` 文件中配置即可，如：`HoaModule.cs`

```csharp
using Autofac;
using Autofac.Extras.DynamicProxy;
using Hoa.Dependencies;
using Hoa.Interceptors;
using System.Linq;

namespace Hoa
{
    public class HoaModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            var registrationBuilder = builder.RegisterAssemblyTypes(AppGlobal.ApplicationAssembiles).PublicOnly()
                   .Where(type => typeof(ITransientDependency).IsAssignableFrom(type))
                   .AsImplementedInterfaces()
                   .InstancePerLifetimeScope();

            if (AppGlobal.AppConfigOptions.EnableGlobalPerformanceAnalysis)
            {
                builder.RegisterType<HoaPerformanceAnalysisInterceptor>().AsSelf();
                registrationBuilder.EnableInterfaceInterceptors().InterceptedBy(typeof(HoaPerformanceAnalysisInterceptor));
            }
        }
    }
}
```

更多 [Autofac](https://autofaccn.readthedocs.io/en/latest/) 配置可查看 [官方文档](https://autofaccn.readthedocs.io/en/latest/)

### .NET Core 自带依赖注入锲约

可查阅 [.NET Core 依赖注入官方文档](https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1)

## 关于生命周期

Hoa Framework框架中集成了`Autofac` 和默认的.NET Core 依赖注入组件，也就是我们可以通过各自提供的方式去控制服务的生命周期。

为了避免常态下手动指定服务生命周期，框架提供了`ITransientDependency`或`IScopeDependency`两个依赖接口。

如果服务直接或间接继承 `ITransientDependency`，生命周期为 `瞬时` 的，也就是只要使用就会创建新对象。

如果服务直接或间接继承 `IScopeDependency`，生命周期为 **基于请求** 的，也就是整个请求只有一个对象。

更多关于生命周期[可查阅官方文档](https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1)。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://monksoul.gitbook.io/hoa/yilaizhurukongzhifanzhuang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
