网站开发 提成,百度推广登录入口登录,wordpress windows伪静态,免费网站软件app如果说在之前的 dotNET 版本中#xff0c;依赖注入还是个比较新鲜的东西#xff0c;那么在 dotNET Core 中已经是随处可见了#xff0c;可以说整个 dotNET Core 的框架是构建在依赖注入框架之上。本文说说对 dotNET Core 中依赖注入的理解。什么是依赖在面向对象的语言中依赖注入还是个比较新鲜的东西那么在 dotNET Core 中已经是随处可见了可以说整个 dotNET Core 的框架是构建在依赖注入框架之上。本文说说对 dotNET Core 中依赖注入的理解。什么是依赖在面向对象的语言中所说的依赖通常指类与类之间的关系比如有个用户类 User 和日志类 Log 在 User 类中需要记录日志就需要引入日志类 Log这样 User 类就对 Log 类产生了依赖代码如下public class User
{private Log _lognew Log();public string GetUserName(){_log.Write(获取用户名称);return oec2003;}
}
public class Log
{public void Write(string message){Console.WriteLine(message);}
}
或者直接在类的方法中对其他类进行了依赖如下public class Dept
{public string GetDeptNameByUserId(string userId){return 开发部;}
}
public string GetUserFullName(string userId)
{Dept deptnew Dept();return $oec2003({dept.GetDeptNameByUserId(userId)});
}
这样的类与类之间的直接依赖有如下几个问题要换一种 Log 的实现方式所有引用的地方都要进行修改如果整个项目中到处都是这种类与类之间的强关联代码维护会变得非常困难对单元测试不友好。要解决上面的问题需要将依赖的类抽象成接口不直接依赖具体的实现类类而是依赖接口这就是面向对象的六大原则中的依赖倒置原则高层模块不应该依赖于底层模块二者都应该依赖于抽象抽象不应该依赖于实现细节实现细节应该依赖于抽象。User 类调整后的代码如下public interface ILog
{void Write(string message);
}
public class Log:ILog
{public void Write(string message){Console.WriteLine(message);}
}
public class User
{private ILog _log;public User(ILog log){_log log;}public string GetUserName(){_log.Write(获取用户名称);return oec2003;}
}
创建了 ILog 接口User 类调整为对 ILog 的依赖在 User 中类添加构造函数在构造函数中传入接口 ILog 的实例。那么构造函数中的实例什么时候创建呢这时就需要用到注入了。什么是注入在上面示例中注入就是在某个时机将 ILog 的实例传递到 User 类的构造函数中而 User 类中根本就不关心 ILog 的实现。在 dotNET Core 中提供了一个内置的服务容器 IServiceProvider然后在 Startup 类的 ConfigureServices 方法中进行注册注册代码如下public void ConfigureServices(IServiceCollection services)
{services.AddSingletonIUser, User();services.AddSingletonILog, Log();services.AddControllers();
}
上面代码中是以单例的模式进行注册将原来在 User 类中的对 Log 类的直接依赖转移到了 ConfigureServices 方法中这便是控制反转IoC了Log 类采用什么实现不在 User 类中来控制而是转移到了框架层面。借助框架的依赖注入相比较我们自己在类中互相关联依赖地去创建对象有以下好处方便管理类之间的依赖对我们使用面向对象的设计原则有帮助代码有更好的维护性和扩展性可以方便管理各个对象的生命周期。依赖注入核心类型在 dotNET Core 中使用内置的依赖注入需要引入 using Microsoft.Extensions.DependencyInjection;i 命名空间。相关的几个核心类型如下IServiceCollection利用此类的扩展方法进行服务的注册IServiceProvider由 IServiceCollection 创建的依赖注入容器体现为IServiceProvider 接口ServiceDescriptor具体注册的服务的描述IServiceProvider 就是通过这个描述来构建我们需要的服务实例ServiceLifetime一个服务生命周期的枚举有 Singleton、Scoped、Transient 三种类型。服务注册的生命周期服务注册的生命周期有三种Singleton单例模式创建在全局的 IServiceProvider 的根容器上Scoped范围模式用 Scope 注册的对象在同一个 ServiceProvider 的 Scope 下相当于单例Transient瞬时模式每次从容器获取对象时都是得到的一个全新的对象。下面用一个示例来看下这三种不同生命周期的区别1、创建分别代表不同生命周期的接口和类代码如下public interface ISingletonService{}
public interface IScopedService{}
public interface ITransientService{}public class SingletonService:ISingletonService{}
public class ScopedService:IScopedService{}
public class TransientService:ITransientService{}
2、在 Controller 中创建接口方法[HttpGet]
public void GetService([FromServices]ISingletonService singleton1,[FromServices]ISingletonService singleton2,[FromServices]IScopedService scoped1,[FromServices]IScopedService scoped2,[FromServices]ITransientService transient1,[FromServices]ITransientService transient2)
{System.Console.WriteLine($singleton1:{singleton1.GetHashCode()});System.Console.WriteLine($singleton2:{singleton2.GetHashCode()});System.Console.WriteLine($scoped1:{scoped1.GetHashCode()});System.Console.WriteLine($scoped2:{scoped2.GetHashCode()});System.Console.WriteLine($transient1:{transient1.GetHashCode()});System.Console.WriteLine($transient2:{transient2.GetHashCode()});
}
3、连续调用两次该接口输入如下图测试示例中每个不同生命周期的对象都通过 FromServices 的方式注入了两次分析结果如下Singleton两次请求的四个对象都相同Scoped相同请求的两个对象是一致重新请求会生成新的对象Transient两次请求的四个对象都不相同每次都构建新的对象。总结依赖注入的目的是为了解耦不依赖于具体类而是依赖抽象类或者接口这叫依赖倒置把服务的注册和实例化的工作交给 dotNET Core 框架而不是在具体实现类中处理这个叫控制反转即IoC (Inversion of Control)就先写到这儿了dotNET Core 框架本身的依赖注入功能已经比较强大但还是有些功能不能满足需要引入第三方的注入框架关于如何引入第三方依赖注入框架以及为什么要用第三方依赖注入框架后面单独开篇写。示例代码https://github.com/oec2003/DotNetCoreThreeAPIDemo/tree/master/InjectDemo