什么是 IOC

Ioc 即 Inversion of Control,即“控制反转”,是一种设计思想,DI(Dependency Injection)叫依赖注入,是对 IoC 更简单的诠释。DI 可以看做是 IOC 的一直实现方式。

什么叫控制反转?何为正转?

  • 既然有反转,那肯定就有正转,何为正转,也就是我们平常直接在程序中进行实例化和构造和对象的依赖。
  • 反转就是不需要我们去关心构建过程和对象的依赖,都有容器来进行控制,即控制的反转。

什么叫依赖注入?

  • 即为从容器中动态的将某个对象注入到组件中去,通过这种机制,我们只需关注使用的对象和业务,不关心对象的来源与创建,提高了系统的灵活性与扩展性。

实现的几种方式(理论)

  • 构造方法注入: 被注入的对象可以通过在其构造方法中声明参数列表,让 IoC 容器知道它需要依赖哪些对象。

  • 属性注入: 在需要注入对象的组件中,加上改对象的实例属性,在使用到时会从容器中自动实例化注入到该组件中。前提是注册到了 IOC 容器中

NetCore3.1 代码实现(属性注入)

代码结构图如下:

结构图

文件说明:

项目文件结构包括:模型领域、业务、数据、控制器、ioc 块、启动程序

在程序启动时,将各个对象注册到容器中,然后在需要使用的地方注入。

程序启动时创建的容器是父容器,每次请求都是从这个父容器中创建一个子容器,都是从这个子容器中构建对象。

安装相关依赖包

先使用Nuget 安装两个所需要的依赖包,Autofac.Extensions.DependencyInjectionAutofac

生命周期说明及对应文件创建

在 Autofac 中依然有三个生命周期对应自带 DI 的三个生命周期:

  • InstancePerDependency 默认生命周期,瞬时的,每次使用都创建一个实例。
  • InstancePerLifetimeScope 单个请求实例唯一,当前请求中使用多次,实例出来的都是一个对象。
  • SingleInstance 全局唯一,单一对象,每个请求每次使用都是一个对象。

因此对应这三个生命周期,创建三个对应的接口,在需要注入的对象上,实现需要注入生命周期对应的接口。在程序启动时注册该对象对应实现接口生命周期。

相关代码实现

Program文件中,相关代码如下:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                 .UseServiceProviderFactory(new AutofacServiceProviderFactory())  //加入这句话 关键
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

Startup.cs文件中 添加对应方法,

        public void ConfigureContainer(ContainerBuilder builder)
        {
            builder.RegisterModule<AutofacModule>();
        }

AutofacModule对应完整代码

using Autofac;
using Demo.IocCommon.AutofacDependency;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Module = Autofac.Module;

namespace Demo.IocCommon
{
    public class AutofacModule : Module
    {
        /// <summary>
        /// 容器初始化
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        protected override void Load(ContainerBuilder builder)
        {
            //所有程序集 和程序集下类型
            var deps = DependencyContext.Default;
            var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project"); //排除所有的系统程序集、Nuget下载包
            var listAllType = new List<Type>();
            foreach (var lib in libs)
            {
                try
                {
                    var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                    listAllType.AddRange(assembly.GetTypes());
                }
                catch
                {
                }
            }

            #region 注册ITransientDependency实现类   瞬时的  默认的

            var dependencyType = typeof(ITransientDependency);
            var arrDependencyType = listAllType.Where(t => dependencyType.IsAssignableFrom(t) && t != dependencyType
               ).ToArray();

            builder.RegisterTypes(arrDependencyType)
                .InstancePerDependency() //每次使用都创建一个新实例   瞬时的  默认的
                .PropertiesAutowired() // 开启属性注入
                ;

            #endregion

            #region 每次请求是唯一实例 IScopedDependency

            var scopeDependencyType = typeof(IScopedDependency);
            var arrScopeDependencyType = listAllType.Where(t => scopeDependencyType.IsAssignableFrom(t) && t != scopeDependencyType
                ).ToArray();

            builder.RegisterTypes(arrScopeDependencyType)
                .InstancePerLifetimeScope() //每次请求是唯一实例
                .PropertiesAutowired() // 开启属性注入
                ;

            #endregion

            #region 单一实例

            var singletonDependencyType = typeof(ISingletonDependency);
            var arrSingletonDependencyType = listAllType.Where(t => singletonDependencyType.IsAssignableFrom(t)
                && t != singletonDependencyType
                ).ToArray();

            builder.RegisterTypes(arrSingletonDependencyType)
                .SingleInstance()
                .PropertiesAutowired();

            #endregion

            #region 注册controller实现类

            var controller = typeof(ControllerBase);
            var arrControllerType = listAllType.Where(t => controller.IsAssignableFrom(t) && t != controller).ToArray();
            builder.RegisterTypes(arrControllerType).PropertiesAutowired();

            #endregion

        }
    }
}

本文使用的是接口注册,当然,也可以使用程序集注册。 程序集注册示例代码:

var iUser = typeof(IUserBll);
builder.RegisterAssemblyTypes(typeof(Program).Assembly).Where(t => iUser.IsAssignableFrom(t) && t != iUser && t.Name.EndsWith("Service")).PropertiesAutowired();

使用结果图如下:

使用

不提倡直接从容器中直接构建对象使用

代码地址

代码地址:github 地址

Copyright © levywang123@gmail.com 2020 all right reserved,powered by Gitbook该文章修订时间: 2020-08-12 11:07:20

results matching ""

    No results matching ""