首页 > 其他分享 >.net 控制反转(IoC)和依赖注入(DI)

.net 控制反转(IoC)和依赖注入(DI)

时间:2023-11-27 16:55:21浏览次数:30  
标签:Name DI t2 t3 t1 services net GetService IoC

引言

控制反转(IoC)实现方法:

  1. (隐式)依赖注入:需要什么服务(类),直接在类里面写,然后系统在创建类的时候给服务(类)自动赋值。
  2. (显式)服务定位器:需要什么服务(类)在给服务定位器要什么服务(类)

1. 初始化使用

引用包:Microsoft.Extensions.DependencyInjection
首先需要创建一个容器:ServiceCollection
然后在容器中注册服务(类)
然后用ServiceProvider获取注册的对象
实例代码:

public interface ITestService
{
    public string Name { get; set; }
    public void SayHi();
}
public class TestServiceImpl : ITestService
{
    public string Name { get; set; }

    public void SayHi()
    {
        Console.WriteLine($"Hi , I'm {Name}");
    }
}
public class TestServiceImpl2 : ITestService
{
    public string Name { get; set; }

    public void SayHi()
    {
        Console.WriteLine($"你好 我是 {Name}");
    }
}
// 容器对象
ServiceCollection services = new ServiceCollection();
// 注册服务
services.AddTransient<TestServiceImpl>();
// 获取注册服务需要用到的工具
using(ServiceProvider serviceProvider = services.BuildServiceProvider())
{
	// 获取注册的服务
    TestServiceImpl test = serviceProvider.GetService<TestServiceImpl>();
    test.Name = "zz";
    test.SayHi();
}

2. 服务使用范围

服务范围分为三种:

  1. 单例:整个容器使用同一个实例对象
  2. 瞬态:每次获取的都是一个新的实例对象
  3. 范围:在一个范围内获取的是同一个实例对象
ServiceCollection services = new ServiceCollection();
//services.AddSingleton<TestServiceImpl>();// 创建单例
services.AddTransient<TestServiceImpl>();// 创建瞬态
//services.AddScoped<TestServiceImpl>();// 创建范围
using (ServiceProvider sp = services.BuildServiceProvider())
{
    TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
    TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
    TestServiceImpl t3 = null;
	// 创建一个范围
    using (IServiceScope scope = sp.CreateScope())
    {
		// 在范围中使用Provider
        t1 = scope.ServiceProvider.GetService<TestServiceImpl>();
        t1.Name = "aa";
        t3 = scope.ServiceProvider.GetService<TestServiceImpl>();
        t3.Name = "dd";
    }
	// 创建一个新的范围
    using(IServiceScope scope = sp.CreateScope())
    {
        t2 = scope.ServiceProvider.GetService<TestServiceImpl>();
        t2.Name = "bb";
    }
    // 单例情况 t1=t2 && t1==t3
    Console.WriteLine(t1==t2 && t1==t3);
    // 瞬态情况 t1!=t2 && t1 != t3
    Console.WriteLine(t1!=t2 && t1 != t3);
    // 范围情况 t1!=t2 && t1 == t3
    Console.WriteLine(t1!=t2 && t1==t3);
    t1.SayHi();
    t2.SayHi();
    t3.SayHi();
}

注册方法和获取实例的方法

ServiceCollection services = new ServiceCollection();
// 注册类与实现类相同
services.AddTransient<TestServiceImpl>();
// 注册类与实现类不同
//services.AddTransient<ITestService,TestServiceImpl>();
// 注册的不同方式,与上面的注册方式结果一致
services.AddTransient(typeof(ITestService),typeof(TestServiceImpl));


// 相同的注册类有多个不同的实现类 
services.AddTransient(typeof(ITestService), typeof(TestServiceImpl2));

using (ServiceProvider sp = services.BuildServiceProvider())
{


    // 如果要获取的注册类不存在GetService则返回null
    TestServiceImpl2 te2 = sp.GetService<TestServiceImpl2>();
    Console.WriteLine(te2);

    // 如果要获取的注册类不存在GetRequiredService则提示错误
    TestServiceImpl2 te3 = sp.GetRequiredService<TestServiceImpl2>();
    Console.WriteLine(te3);


    // 使用注册类获取想要的类
    TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
    // 使用注册类获取想要的类
    //ITestService t2 = sp.GetService<ITestService>();
    // 不使用泛型获取对象 需要手动转换类型 与上面结果一致
    ITestService t2 = (ITestService)sp.GetService(typeof(ITestService));
    t1.Name = "aa";
    t1.SayHi();
    t2.Name = "bb";
    t2.SayHi();

    // 注册多个不同的实现类,如果使用GetService则获取最后注册的实现类
    ITestService t3 = sp.GetService<ITestService>();
    t3.Name = "cc";
    t3.SayHi();

    // 获取多个不同的实现类用GetServices
    IEnumerable<ITestService> t4 = sp.GetServices<ITestService>(); 
    foreach (ITestService t in t4)
    {
        t.Name = "11";
        t.SayHi();
    }

}

标签:Name,DI,t2,t3,t1,services,net,GetService,IoC
From: https://www.cnblogs.com/sunhouzi/p/17859733.html

相关文章

  • Spring Data Redis切换底层Jedis 和 Lettuce实现
    1简介SpringDataRedis是SpringData系列的一部分,它提供了Spring应用程序对Redis的轻松配置和使用。它不仅提供了对Redis操作的高级抽象,还支持Jedis和Lettuce两种连接方式。可通过简单的配置就能连接Redis,并且可以切换Jedis和Lettuce两个连接方式。下面先来看看我们该如何使......
  • Discuz3.5版本整合Java 登录
    1.下载Discuz下载:官网Discuz-api-for-java下载:蓝奏云2.配置1.登录ucenter后台,应用管理,新建一个应用。以上配置uCenter如果能访问到http://172.16.22.103:13000/api/uc.php,就会显示通信成功2.修改Java配置运行testLogin()方法,如果不出意外会得到一个js代码,例:<scripttype="text/......
  • 转:在.NET FX 4.8项目中使用C# 8/9/10的新语法
    在.NETFX4.8项目中使用C#8/9/10的新语法吴冬wdhustInnovativeBIMtechniques 受到某些特殊原因的限制,有时候.NET项目被锁死在.NETFramework4.8,而无法升级到.NET5等更高版本,导致代码中能够使用的C#语法最高只能支持到C#7.3,而无法使用C#8及更高版......
  • vue3使用kindeditor富文本编辑器组件,支持上传图片(接口或base64)
    参考文章:https://blog.csdn.net/qq_27936291/article/details/1247689891.安装插件npmi@zhj-target/vue3-kind-editor--save或者yarnadd@zhj-target/vue3-kind-editor2.在vue项目中使用importVue3KindEditorfrom'@zhj-target/vue3-kind-editor'conststate=re......
  • Redis的基本常识
    Redis简介:Redis是完全开源的,遵守BSD协议,是一个高性能的key-value数据库。Redis与其他key-value缓存产品有以下三个特点:Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。Redis不仅仅支持简单的key-value类型的数据,同时还提供l......
  • 构建卓越Kubernetes安全之路:最佳实践与军规
    Kubernetes作为现代云原生计算的中流砥柱,其安全性是我们构建稳健应用生态的首要任务。在这篇博文中,我们将探讨构建卓越Kubernetes安全的道路,通过最佳实践和制定安全军规,确保您的集群免受威胁。1. 了解威胁与风险在开始构建安全之旅之前,深入了解可能的威胁和风险是关键一步。考虑容......
  • Linux编译方式安装redis
    redis安装1、安装gcc-c++编译环境yuninstallgcc-c++2、把redis上传到linux服务器3、解压缩  tar-zxfredis-3.0.0.tar.gz4、make5、安装并指定安装目录 需要创建目录/usr/local/redismakeinstallPREFIX=/usr/local/redis安装完显示结尾为 INSTALLinstall make[1]......
  • 快速入门:使用 Azure CLI 部署 Azure Kubernetes 服务 (AKS) 群集
    原文:https://learn.microsoft.com/zh-cn/azure/aks/learn/quick-kubernetes-deploy-cli本文内容开始之前创建资源组创建AKS群集连接到群集显示另外4个AzureKubernetes服务(AKS)是可用于快速部署和管理群集的托管式Kubernetes服务。在本快速入门中,请执行以下操......
  • Codeforces Round 911 (Div. 2) A-C
    CodeforcesRound911(Div.2)A.CoverinWater题意:有n个单元格,有的空着有的被堵住,可以做两种操作:给一个空着的单元格放入水;将单元格的水移到另一个单元格。并且,若一个单元格左右两边都有水,它也会自动充满水。所有空着的单元格都要充满水,求最少的放入水的次数思路:若存在三......
  • python threading线程数
    importthreadingimporttimename_list=[{"李四1":1234556},{"李四2":1234556},{"李四3":1234556},{"李四4":1234556},{"李四5":1234556},{"李四6":1234556},{"李四7"......