您现在的位置是:首页 >学无止境 >.Net6.0系列-8 依赖注入(一)网站首页学无止境

.Net6.0系列-8 依赖注入(一)

奇点码农 2023-05-19 16:00:02
简介.Net6.0系列-8 依赖注入(一)

依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式,依赖注入简化模块的组装过程,降低模块之间的耦合度.
DI的几个概念:
服务(Service):和框架请求之后返回的一个对象,可以是一个数据库链接,也可以是一个文件处理的方法,或者是数据处理的一个过程方法
注册服务:将上面向框架要的这个服务先注册,才能向框架请求
服务容器:负责管理注册的服务
查询服务:创建对象及关联对象
对象生命周期有三种:
(1)Transient(瞬态):获取服务对象每次获取都是一个新的对象
(2)Scoped(范围):在特定范围内再次获取为同一个对象
(3)Singleton(单例):就这一个对象,每次获取都是他
如果一个类实现了IDisposable接口,则离开作用域后容器会自动调用对象的Dispose方法,参考Using
生命周期的选择:如果类无状态,建议选为Singleton,如果类中有状态且有Scope控制就使用Scoped

.Net中使用DI
1.根据类型来获取和注册服务:
可以分别指定服务类型和实现类型.这两者可能相同,也可能不同.服务类型可以是类,也可以是接口,一般面向接口编程更灵活
2…Net控制反转组件取名为DependencyInjection,但是包含ServiceLocator的功能
3.ServiceCollection用来构造容器对象IServiceProvider,调用ServiceCollection的BuliderServiceProvider()创建ServiceProvider,可以用来获取BuliderServiceProvider()之前ServiceCollection中的对象
安装包需求:
Install-Package Microsoft.Extensions.DependencyInjection
using Microsoft.Extensions.DependencyInjection

GetService是根据注册对象来返回的
GetRequiredService:没有服务就抛出异常,因为required是必须有服务,当有多个服务的时候获取的是最后一个服务
GetServices:获取注册的所有的服务,

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}");
	}
}

static void Main(string[] args)
{
	#region 直接注册实现类,和接口没有关系,将实现类注册到服务容器中,然后通过实现类获取服务
	ServiceCollection services=new ServiceCollection();
	services.AddTransient<TestServiceImpl>();
	//下面是两种申请服务的方法,一种是sp.GetServices/一种是sp.CreateScope()
	using(ServiceProvider sp= services.BulidServiceProvider())
	{
		TestServiceImpl tsi=sp.GetService<TestServiceImpl>();
		t.Name="cdc";
		t.SayHi();
        using(IServiceScope scope1=sp.CreateScope())
        {
			TestServiceImpl t=scope1.ServiceProvider.GetService<TestServiceImpl>();
		}
	}
	#endregion
}

static void Main(string[] args)
{
	ServiceCollection services=new ServiceCollection();
	//注册类型是接口,实现类型是方法
	services.AddScoped<ITestService,TestServiceImpl>();
	//这种写法是为了传参数
	services.AddSingleton<ITestService,new TestServiceImpl()>
	using(ServiceProvider sp=services.BulidServiceProvider())
	{
		ITestService ts1=sp.GetService<ITestService>();
		//ITestService ts1=(ITestService)sp.GetService(typeof(ITestService));
		ts1.Name="cdc";		
		ts1.SayHi();		
	}

}


DI会传染的简单范例

namespace DIGOALL
{
	class Progrom
	{
		static void Main(string[] args)
		{
			ServiceClolection services=new ServiceCollection();
			services.AddScoped<Controller>();
			services.AddScoped<ILog,LogImpl>();
			services.AddScoped<IStorage,StorageImpl>();
			services.AddScoped<IConfig,ConfigImpl>();
			using(var sp= services.BulidServiceProvider())
			{
				var c=sp.GetRequiredService<Controller>();
				c.Test();
			}
			Console.ReadKey();
		}
	}
	class  Controller
	{
		private readonly ILog log;
		private readonly IStorage storage;
		public Controller(ILog log,IStorage storage) 
		{
			this.log=log;
			this.storage=storage;
		}
	
		public void Test()
		{
			this.log.Log("开始上传");
			this.storage.Save("写入的东西","1.txt");
			this.log.Log("上传完毕");
		}
	}
	
	#region 日志类
	interface ILog
	{
		public void Log(string msg);
	}
	class LogImpl:ILog
	{
		public void Log(string msg)
		{
			Console.WriteLine($"日志:{msg}");
		}
	}
	#endregion
	
	#region 
	interface IConfig
	{
		public string GetValue(string name);
	}
	class ConfigImpl:IConfig
	{
		public void GetValue(string name)
		{
		 	return "hello";
		}		
	}
	#endregion
	
	#region 云存储
	interface IStorage
	{
		public void Save(string content,string name);
	}
	class StorageImpl:IStorage
	{
		**关键点:获取配置服务,构造函数中赋值给成员变量**
		private readonly IConfig config;		
		public StorageImpl(IConfig config)
		{
			this.config=config;
		}
		public void Save(string content,string name)
		{
			string server=config.GetValue("server");
			Console.WriteLine($"向服务器{server}的文件名为{name}上传{content}");
		}
	}
	#endregion
}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。