.NET 5.0 依赖注入

参考:

https://www.cnblogs.com/zoro-zero/p/13490459.html

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

DI:是一种软件设计模式,Asp.net core支持该模式。这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。

依赖项:指另一个对象所依赖的对象。

常见的DI框架:Autofac、Unity......

依赖关系注入概述——  谁依赖谁,将谁注入谁

依赖注入是指在创建一个对象时,自动地创建它所依赖的对象,并注入。

依赖注入的方式:1.构造方法注入;  2.Set方法注入;  3.方法参数注入

1.构造方法注入:

优点:

  • 在构造方法中体现出对其他类的依赖,直接就可以看出这个类所需要的依赖那些类才能工作。
  • 脱离了IOC框架,这个类仍然可以工作。
  • 一旦对象初始化成功了,这个对象的状态肯定是正确的。

缺点:

  • 构造函数会有很多参数(Bad smell)。
  • 有些类是需要默认构造函数的,比如MVC框架的Controller类,一旦使用构造函数注入,就无法使用默认构造函数。
  • 这个类里面的有些方法并不需要用到这些依赖(Bad smell)。

2.Set方法注入

优点:

  • 在对象的整个生命周期内,可以随时动态的改变依赖。
  • 非常灵活。

缺点:

  • 对象在创建后,被设置依赖对象之前这段时间状态是不对的。
  • 不直观,无法清晰地表示哪些属性是必须的。

3.方法参数注入--即以入参的方法,将对象赋值给方法内的对象

方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。类似如下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

public class MovieRecommender {

  

 private MovieCatalog movieCatalog;

 public class MovieRecommender {

  

  private MovieCatalog movieCatalog;

  

  private CustomerPreferenceDao customerPreferenceDao;

  

  @Autowired

  public void prepare(MovieCatalog movieCatalog,

                      CustomerPreferenceDao customerPreferenceDao) {

      this.movieCatalog = movieCatalog;

      this.customerPreferenceDao = customerPreferenceDao;

  }

  

  // ...

}

  private CustomerPreferenceDao customerPreferenceDao;

  

  public void prepare(MovieCatalog movieCatalog,

                      CustomerPreferenceDao customerPreferenceDao) {

      this.movieCatalog = movieCatalog;

      this.customerPreferenceDao = customerPreferenceDao;

  }

  

  // ...

}

一般只有一个方法依赖到注入的对象时用到

如果有多个方法依赖到注入的对象,还是使用构造方法注入方式比较合适

优点:

  • 比较灵活。

缺点:

  • 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦。
  • 与构造方法注入一样,会有很多参数。

依赖注入使用注意事项:

1.使用接口或基类将依赖关系实现抽象化

2.在服务容器中注册依赖关系。 ASP.NET Core 提供了一个内置的服务容器 IServiceProvider。 服务通常已在应用的 Startup.ConfigureServices 方法中注册。

3.将服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。

如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

using System;

namespace Models

{

    public interface IMyDependency

    {

        void WriteMessage(string message);

    }

}

using System;

namespace Models

{

    /// <summary>

    /// 示例应用使用具体类型 MyDependency 注册 IMyDependency 服务

    /// </summary>

    public class MyDependency : IMyDependency

    {

        /// <summary>

        /// 传参注入

        /// </summary>

        /// <param name="message">依赖项</param>

        public void WriteMessage(string message)

        {

            Console.WriteLine($"MyDependency.WriteMessage Message: {message}");

        }

    }

}注:以上示例应用使用具体类型 MyDependency 注册 IMyDependency 服务;

AddScoped 方法使用范围内生存期(单个请求的生存期)注册服务

public void ConfigureServices(IServiceCollection services)

{

  services.AddScoped<IMyDependency, MyDependency>(); services.AddRazorPages();

}在示例应用中,请求 IMyDependency 服务并用于调用 WriteMessage 方法:

namespace Models.Model.Demo1

{

    public class OneModel

    {

        private readonly IMyDependency _myDependency;

        public OneModel(IMyDependency myDependency)

        {

            _myDependency = myDependency;

        }

        public void OnGet()

        {

            _myDependency.WriteMessage("OneModel.OnGet");

        }

    }

}

namespace Models.Model.Demo1

{

    public class MyDependency2 : IMyDependency

    {

        private readonly ILogger<MyDependency2> _logger;

        /// <summary>

        /// 构造注入

        /// </summary>

        /// <param name="logger">依赖项</param>

        public MyDependency2(ILogger<MyDependency2> logger)

        {

            _logger = logger;

        }

        /// <summary>

        /// 传参注入

        /// </summary>

        /// <param name="message">依赖项</param>

        public void WriteMessage(string message)

        {

            _logger.LogInformation($"MyDependency2.WriteMessage Message: {message}");

        }

    }

}

通过使用 DI 模式,表示控制器:

  • 不使用具体类型 MyDependency,仅使用它实现的 IMyDependency 接口。 这样可以轻松地更改控制器使用的实现,而无需修改控制器。
  • 不创建 MyDependency 的实例,这由 DI 容器创建。

可以通过使用内置日志记录 API 来改善 IMyDependency 接口的实现:using Microsoft.Extensions.Logging;

更新的 ConfigureServices 方法注册新的 IMyDependency 实现:
public void ConfigureServices(IServiceCollection services) 
{ 
  services.AddScoped<IMyDependency, MyDependency2>(); 
}
MyDependency2 依赖于 ILogger<TCategoryName>,并在构造函数中对其进行请求。 ILogger<TCategoryName> 是框架提供的服务

1

必须被解析的依赖关系的集合通常被称为“依赖关系树”、“依赖关系图”或“对象图”

容器通过利用(泛型)开放类型解析 ILogger<TCategoryName>,而无需注册每个(泛型)构造类型

在依赖项注入术语中,服务:

  • 通常是向其他对象提供服务的对象,如 IMyDependency 服务。
  • 与 Web 服务无关,尽管服务可能使用 Web 服务。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何时才能相遇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值