什么是依赖注入
依赖
当一个类需要另一个类协作来完成工作的时候就产生了依赖。比如我们在下面这个示例,我在DemoService里面拟定了一个方法,输出个人信息。所以这里面就有了一IDemoService 的依赖。
这里有一个设计原则:依赖于抽象,而不是具体的实现。所以我们给DemoService定义了一个接口,抽象了DemoService的行为。
很多时候,我们如果要在某个Controller或者其他地方引用其他类,我们一般会这样调用
IDemoService _ds; public MainController() { _ds = new DemoService(); }
其实,这样写也可以,但是这样不太好,不应该自己去创建他,而是应该由你的调用者给你。于是你通过构造函数让外界把这两个依赖传给你。
就像酱紫:
IDemoService _ds; public MainController(IDemoService ds) { this._ds = ds; }
把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。
.NET Core DI
实例的注册
一共提供有三种方法
var serviceCollection = new ServiceCollection() .AddTransient<ILoginService, EFLoginService>() .AddSingleton<ILoginService, EFLoginService>() .AddScoped<ILoginService, EFLoginService>();
Transient: 每一次GetService都会创建一个新的实例
Scoped: 在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
Singleton :整个应用程序生命周期以内只创建一个实例
对应了Microsoft.Extensions.DependencyInjection.ServiceLifetime的三个枚举值
public enum ServiceLifetime { Singleton, Scoped, Transient }
生命周期之单例模式(Singleton)
为了大家能够更好的理解这个生命周期的概念我们做一个测试:
定义一个最基本的IOperation里面有一个 OperationId的属性,IOperationSingleton也是一样,只不过是另外一个接口。
public interface IOperation { Guid OperationId { get ; } } public interface IOperationSingleton : IOperation { } public interface IOperationTransient :IOperation{} public interface IOperationScoped : IOperation{}
这个Operation实现很简单,可以在构造函数中传入一个Guid进行赋值,如果没有的话则自已New一个 Guid。
public class Operation : IOperationSingleton, IOperationTransient, IOperationScoped { private Guid _guid; public Operation() { _guid = Guid.NewGuid(); } public Operation(Guid guid) { _guid = guid; } public Guid OperationId => _guid; }
在程序内我们可以多次调用ServiceProvider的GetService方法,获取到的都是同一个实例。
// 默认构造 services.AddSingleton<IOperationSingleton, Operation>(); // 自定义传入Guid空值 services.AddSingleton<IOperationSingleton>( new Operation(Guid.Empty)); // 自定义传入一个New的Guid services.AddSingleton <IOperationSingleton>( new Operation(Guid.NewGuid())); var provider = services.BuildServiceProvider(); // 输出singletone1的Guid var singletone1 = provider.GetService<IOperationSingleton>(); Console.WriteLine($ "signletone1: {singletone1.OperationId}" ); // 输出singletone2的Guid var singletone2 = provider.GetService<IOperationSingleton>(); Console.WriteLine($ "signletone2: {singletone2.OperationId}" ); Console.WriteLine($ "singletone1 == singletone2 ? : { singletone1 == singletone2 }" );
这个示例对IOperationSingleton注册了三次,最后获取两次,大家要注意到我们获取到的始终都是我们最后一次注册的那个给了一个Guid的实例,前面的会被覆盖。
生命周期之Scoped
.NET Core人IServiceProvider提供CreateScope产生一个新的ServiceProvider范围,在这个范围下的Scope标注的实例将只会是同一个实例。换句话来说:用Scope注册的对象,在同一个ServiceProvider的 Scope下相当于单例。
微信扫码查看本文
发表评论