写在前面:
上文我们已经将整个项目的整体框架完整搭建了,正常来说我们已经可以可以开始处理我们的业务了。上文的最后我们埋下了一个伏笔,就是如果我的项目有100个实体类,难道我需要每次在使用的时候都去初始化吗?今天我们就来解决这个问题。
1.0 依赖注入DI:
1.1:什么是依赖注入
由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。
1.2:依赖注入的好处:
- 传统的代码,每个对象负责管理与自己需要依赖的对象,导致如果需要切换依赖对象的实现类时,需要修改多处地方。同时,过度耦合也使得对象难以进行单元测试。
- 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制。
松耦合让代码更具灵活性,能更好地应对需求变动,以及方便单元测试。
1.3:依赖注入的三种方式:
1:构造函数注入(最常用)
- 2:属性注入(使用get,set注入)
- 3:方法注入
示例:
public IUserDao _userDao;
public UsersController(IUserDao userDao) //构造函数注入
{
_userDao = userDao;
}
public void SetUserDao(IUserDao userDao) //方法注入
{
_userDao = userDao;
}
public IUserDao UserDao
{ //属性注入
set { _userDao = value; }
}
2.0:控制反转IOC:
2.1:什么是控制反转:
是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
2.2:常见的IOC框架:
- Autofac:貌似目前net下用的最多吧
- Ninject:目前好像没多少人用了
- Unity:也是较为常见
- 微软 core 自带的 DI
2.3:微软自带的DI三种注入方式及生命周期:
AddSingleton<>();//Singleton(单例) 服务在第一次请求时被创建(或者当我们在ConfigureServices中指定创建某一实例并运行方法),其后的每次请求将沿用已创建服务。如果开发者的应用需要单例服务情景,请设计成允许服务容器来对服务生命周期进行操作,而不是手动实现单例设计模式然后由开发者在自定义类中进行操作。
AddTransient<>();//服务在每次请求时被创建,它最好被用于轻量级无状态服务
AddScoped<>();//服务在每次请求时被创建,生命周期横贯整次请求
权重:
AddSingleton→AddTransient→AddScoped
AddSingleton的生命周期:
项目启动-项目关闭 相当于静态类 只会有一个
AddScoped的生命周期:
请求开始-请求结束 在这次请求中获取的对象都是同一个
AddTransient的生命周期:
请求获取-(GC回收-主动释放) 每一次获取的对象都不是同一个
3.0:AutoFac的使用:
3.1:引入AutoFac
打开NuGet程序包,搜索AutoFac
分别引入一下两个程序包。
打开项目的Program.cs
program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())//添加Auofac服务
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
然后在项目的Startup.cs中新增以下方法:
Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
var servicesDllFile = Path.Combine(basePath, "Blog.Services.dll");//获取注入项目绝对路径
var repositoryDllFile = Path.Combine(basePath, "Blog.Repository.dll");
var assemblysServices = Assembly.LoadFrom(servicesDllFile);//直接采用加载文件的方法
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);//直接采用加载文件的方法
builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors();
builder.RegisterAssemblyTypes(assemblysRepository)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors();
}
这种方式将Repository与Sercices层与我们的API层分开,这样以后不论Repository与Sercices层如何改变,我们都不需要修改API层代码。
我们需要将Services,Repository层的dll生成到API层中去。
写在后面:
通过以上的方式我们使用Autofac实现了项目的依赖注入,前路漫漫,未完待续。。。