找回密码
 立即注册
快捷导航

[.NET] IoC控制反转/DI依赖注入 、 生命周期 与 注入方式

[复制链接]
狗蛋 2023-7-7 18:09:06 | 显示全部楼层
loC是 Inversion of Control(控制反转)的缩写,不是什么技术,而是一种面向对象编程的设计模式(设计思想)

在传统的面向对象编程中,应用程序主动创建和管理所有对象及其依赖关系。而在IOC模式中,控制权被反转,由 容器 来负责管理对象及其依赖关系。(以前是你要什么就创建什么,现在是你要什么容器就给你什么,这就是控制反转过来了)这样做有助于降低代码之间的耦合性,提高代码的可重用性、可维护性和可测试性。

在传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;
有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整人体系结构变得非常灵活;

维基百科:依赖注入是一种软件设计模式。指一个或多个依赖(或服务)被注入,或通过引用传递,传入一个依赖对象(或客户端)并成为客户状态的一部分。该模式通过自身的行为分离了客户依赖的创建,这允许程序设计是松耦合的同时遵循 依赖倒到置单一职责 原则。与服务定位器模式直接进行对比,它允许用户了解他们用来查找依赖的机制。

在IoC模式中,通常使用依赖注入(Dependency Injection, DI)来实现对象之间的依赖关系。通过依赖注入,容器将所需的依赖关系注入到对象中,对象只需要专注于完成自已的任务,不需要关注如何获取依赖关系。

依赖注入DI 是 实现控制反转IoC的方式 之一

DI的实现包括:依赖抽象而不要依赖具体的实现!

注入方式:

  • 构造函数注入
  • 方法注入
  • 属性注入

生命周期

  • 单例
  • 瞬时
  • 作用域
创建一个asp.net core web api 项目WebApplication1,新建两个类库,一个是 Interface,另一个是 Saervice

// 用户服务接口
namespace WebApplication1.Interface{
    public interface IUserService{
        public string GetName();
    }
}

// -------------------------------------

// 用户服务实现类
using WebApplication1.Interface;
namespace WebApplication1.Service{
    public interface UserService: IUserService{
        public string GetName(){
            return "zhangsan";
        }
    }
}

准备好上面的接口和服务之后,就可以通过依赖注入方式去使用了:

//Program.cs

using WebApplication1.Interface;
using WebApplication1.Service;

//注册服务
builder.Services.AddScoped<IUserService, UserService>();

// 在路由终结点中通过方法注入使用
app.MapGet("/GetName",(IUserService user)=>
{
    return user.GetName();
});

上面例子中虽然我可以直接 new UserService() 对象出来,但是这破坏了 开闭原则,我们应该依赖抽象(接口)而不是依赖具体的实现(对象);

IoC的 生命周期

在IOC容器中,常见的对象生命周期有以下:

1、瞬态(Transient):每次从Ioc容器请求获取对象时,都会创建一个新的实例。每个对象实例在使用后都会被销毁。这种生命周期适用于无状态的对象,不需要在多个地方共享或保留状态。

2、单例(Singleton):在整个应用程序中只会创建一个实例,并且每次从IoC容器请求获取对象时都会返回同一个实例。这意味着该对象会被重用,并且在整个应用程序生命周期内保持唯一。单例对象通常用于表示应用程序中的共享资源或全局服务。

3、作用域(Scoped):在每个作用域(例如HTTP请求)中创建一个实例,并且在同一个作用域内多次请求获取对象时都返回同一个实例。在不同的作用域中,将创建新的实例。这种生命周期适用于需要在特定作用域内共享对象实例的情况,比如Web应用程序中的每个HTTP请求。

//builder.Services.AddTransient<IUserService,UserService>();
//builder.Services.Addsingleton<IUserService,UserService>();
//builder.Services.AddScoped<IUserService,UserService>();

这些生命周期的区别主要在于:对象实例的创建和销毁方式,以及对象的重用性。

  • 瞬态      创建和销毁对象的开销较大,适用于无状态对象;
  • 单例      减少了对象的创建和销毁开销,并且提供全局唯一的对象实例;
  • 作用域   适用于需要在特定作用域内共享对象的情况,可以在不同作用域之间创建不同的对象实例。

需要注意的是,不同的IoC容器实现可能对生命周期的实现方式有所不同。以上是一股情况下的常见生命周期,具体实现可以根据不同的IOC容器和框架进行调整和配置。

注入方式

在IoC容器中,注入方式有以下几种:

1、构造函数注入(Constructor Injection):通过类的构造函数来注入依赖项。在创建类的实例时,依赖项作为构造函数的参数进行传递。这是 最常用的注入方式之一,能够确保依赖项在对象创建时被传入,并且在整个对象生命周期中保持不变。

2、属性注入(Property Injection):通过类的 公共属性 来注入依赖项。依赖项通过属性的Setter方法进行注入。在对象创建后,IOC容器会自动设暨相应的属性值。相比构造函数注入,属性注入更加灵活,可以在对象创建后动态地注入依赖项。

3、方法注入(Method Injection):通过类的 公共方法 来注入依赖项。依赖项作为方法的参数进行传递。在对象创建后,IOC容器会调用相应的方法,并传入依赖项。方法注入通常在对象创建后需要进行一些特定的初始化操作时使用。

这些注入方式可以单独使用,也可以组合使用,根据具体的需求和依赖关系来选择适当的方式。注入方式的选择也取决于使用的IOC容器和框架,不同的容器可能对注入方式有所不同。

注意:内置的DI依赖注入只支持构造函数注入,如果想支持属性或方法的注入,请使用第三方依赖注入比如 Autofac 去注入





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

温馨提示

关于 注册码 问题

      由于近期经常大量注册机器人注册发送大量广告,本站开启免费入群领取注册码注册网站账号,注册码在群公告上贴着...

关于 注册码 问题

      由于近期经常大量注册机器人注册发送大量广告,本站开启免费入群领取注册码注册网站账号,注册码在群公告上贴着...

Archiver|手机版|小黑屋|DLSite

GMT+8, 2024-11-23 00:44

Powered by Discuz! X3.5 and PHP8

快速回复 返回顶部 返回列表