依赖注入

依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。

两种实现方式:

1)服务定位器(ServiceLoccator);

2)依赖注入(Dependency Injection,DI)

DI相关概念

1)服务(Service):对象 即使用者需要的内容;

2)注册服务:服务与其实现的关系;

3)服务容器:负责管理注册的服务;

4)查询服务:创建对象;

5)对象声明周期:Transient(瞬态);Scoped(范围);Singleton(单例);

.Net中使用DI(概念)

1)根据类型来注册和获取服务,可以分别指定服务类型(Service Type)和实现类型(Implementation Type)。这两者可能相同,也可能不同。服务类型可以是具体的实现类,也可以是接口,建议面向接口编程。

2).NET控制反转组件名称为:DependencyInjection,它包含ServiceLocator的功能。

.Net中使用DI(实现)

1)安装对应包并引用,Install-Package Microsoft.Extensions.DependencyInjection

2)ServiceCollection用来构造容器对象IServiceProvider。 具体调用ServiceCollection的BuildServiceProvider方法。可以用来获取调用BuildServiceProvider之前已注册的服务。

using System;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var services = new ServiceCollection();//创建服务集合
            services.AddScoped<TestServiceImp1>();//注册一个瞬态服务
            services.AddScoped<ITestService, TestServiceImp2>();//以接口、服务类型的方式注册 方式1
            //services.AddScoped(typeof(ITestService), typeof(TestServiceImp2));//以接口、服务类型的方式注册 方式2
            using (var serviceProvider = services.BuildServiceProvider())//创建一个服务提供者
            {
                var testservice = serviceProvider.GetService<TestServiceImp1>();
                testservice.SayHi();
            }
        }    
    }
    public interface ITestService
    {
        public string Name { get; set; }

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

        public void SayHi()
        {
            Console.WriteLine($"hi,I am {Name}");
        }
    }
    public class TestServiceImp2 : ITestService
    {
        public string Name { set; get; }

        public void SayHi()
        {
            Console.WriteLine($"你好,我是{Name}");
        }
    }   
}
依赖注入例子(服务定位器)

 

例子2
using System;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleApp1
{
	internal class Program
	{
		static void Main(string[] args)
		{
			IServiceCollection services = new ServiceCollection();
			//方法1:万能公式 其它的都是扩展方法,本质调用的还是这个万能公式,包括委托的方式(他的实现类型是一个委托)
			services.Add(new ServiceDescriptor(typeof(ISerivce), typeof(Service), ServiceLifetime.Singleton));
			//方法2:泛型接口
			services.AddSingleton<ISerivce, Service>();
			//方法3:反射接口 反射的方式在编写框架时十分有用,无反射无框架
			services.AddSingleton(typeof(ISerivce), typeof(Service));
			//方法4:委托方式  当我们构建的对象需要编写逻辑时,委托方式十分有用			
			services.AddSingleton<IDbConnection>(sp =>
			{
				//获取参数逻辑
				return new DbConnection("127.0.0.1");
			});
			//方法5:泛型注册 注册泛型时,只能使用反射接口,并且泛型参数不要写入,解析时来确立,如果有多个泛型参数使用逗号隔开
			services.AddSingleton(typeof(ILogger<>), typeof(ConsoleLogger<>));
			var con = services.BuildServiceProvider();
			var service1 = con.GetRequiredService<ISerivce>();
			var service2 = con.GetRequiredService<IDbConnection>();
			var service3 = con.GetRequiredService<ILogger<DbConnection>>();
		}
	}

	public interface ISerivce
	{ }

	public class Service : ISerivce
	{ }

	public interface IDbConnection
	{ }

	public class DbConnection : IDbConnection
	{
		public DbConnection(string connectionStr)
		{
			Console.WriteLine($"use {connectionStr} connect succeed!");
		}
	}

	public interface ILogger<T>
	{ }

	public class ConsoleLogger<T> : ILogger<T>
	{
		public ConsoleLogger()
		{
			Console.WriteLine($"T is {typeof(T)}");
		}
	}
}

IServiceProvider的服务定位器常用方法

1)T T? GetService<T>() 如获取不到对象,则返回Null

2)objcet GetService(Type serviceType)  一般搭配反射使用

3)T GetRequiredService<T>() 如果获取不到对象,则抛出异常

4)objcet GetRequiredService(Type serviceType)

5)IEnumerable<T> GetServices<T>() 适用于一个服务类型有多个实现对象

6)IEnumerable<object?> GetServices(Type serviceType)

 

posted @ 2022-02-17 13:22  小毛备忘录  阅读(63)  评论(0)    收藏  举报