> For the complete documentation index, see [llms.txt](https://monksoul.gitbook.io/hoa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://monksoul.gitbook.io/hoa/yilaizhurukongzhifanzhuang.md).

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

## 依赖注入（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)。
