在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期.
.netcore内置依赖注入,通过services.AddTransient、services.AddScoped、services.AddSingleton这些方法即可实现构造函数注入。
微软给自行注入的服务,提供了3种生命周期.
Transient(瞬时的)
每次请求时都会创建的瞬时生命周期服务。这个生命周期最适合轻量级,无状态的服务。
Scoped(作用域的)
在同作用域,服务每个请求只创建一次。
Singleton(唯一的)
全局只创建一次,第一次被请求的时候被创建,然后就一直使用这一个.
如何使用这三种生命周期呢?.我们直接在注入的时候用不同的方法就行了,代码如下:
//注册不同生命周期的服务
services.AddTransient<ITestService, TestService>(); services.AddScoped<ITestService2, TestService2>(); services.AddSingleton<ITestService3, TestService3>();
自带的IOC 做一些小的项目完全没有问题,但是大项目使用起来就比较单一,所以我们将默认的IOC容器替换为Autofac
Autofac可完美替换系统的依赖注入功能,可实现构造函数注入和属性注入,替换过程:
在Program.cs 新增一行代码
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory())//集成Autofac .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
然后在Startup.cs 增加方法
//集成Autofac public void ConfigureContainer(ContainerBuilder builder) { //添加依赖注入实例,AutofacModuleRegister就继承自Autofac.Module的类 builder.RegisterModule(new StartupHelp.AutofacModuleRegister()); }
ConfigureAutofac 是自己封装的一个类 继承了 Autofac.Module
其中注册类必须继承自Autofac.Module,并且在Load中实现注入,此处应用了程序集范围的注入以及单个对象的注入,最后添加的代码是为了支持控制器的属性注入。
注入的接口(如IUnitOfWork)和实现(UnitOfWork)没有特别。
注入对象的生命周期与.netcore内置的一致
public class AutofacRegister : Autofac.Module { #region 单个类和接口 //直接注册某一个类和接口 //左边的是实现类,右边的As是接口 //containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance(); //这里就跟默认DI差不多 //services.AddScoped<TestServiceE, ITestServiceE>(); #endregion #region 方法1 Load 适用于无接口注入 //var assemblysServices = Assembly.Load("Exercise.Services"); //containerBuilder.RegisterAssemblyTypes(assemblysServices) // .AsImplementedInterfaces() // .InstancePerLifetimeScope(); //var assemblysRepository = Assembly.Load("Exercise.Repository"); //containerBuilder.RegisterAssemblyTypes(assemblysRepository) // .AsImplementedInterfaces() // .InstancePerLifetimeScope(); #endregion #region 方法2 选择性注入 与方法1 一样 // Assembly Repository = Assembly.Load("Exercise.Repository"); // Assembly IRepository = Assembly.Load("Exercise.IRepository"); // containerBuilder.RegisterAssemblyTypes(Repository, IRepository) //.Where(t => t.Name.EndsWith("Repository")) //.AsImplementedInterfaces().PropertiesAutowired(); // Assembly service = Assembly.Load("Exercise.Services"); // Assembly Iservice = Assembly.Load("Exercise.IServices"); // containerBuilder.RegisterAssemblyTypes(service, Iservice) //.Where(t => t.Name.EndsWith("Service")) //.AsImplementedInterfaces().PropertiesAutowired(); #endregion #region 方法3 使用 LoadFile 加载服务层的程序集 将程序集生成到bin目录 实现解耦 不需要引用 //获取项目路径 //var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath; //var ServicesDllFile = Path.Combine(basePath, "Exercise.Services.dll");//获取注入项目绝对路径 //var assemblysServices = Assembly.LoadFile(ServicesDllFile);//直接采用加载文件的方法 //containerBuilder.RegisterAssemblyTypes(assemblysServices).AsImplementedInterfaces(); //var RepositoryDllFile = Path.Combine(basePath, "Exercise.Repository.dll"); //var RepositoryServices = Assembly.LoadFile(RepositoryDllFile);//直接采用加载文件的方法 //containerBuilder.RegisterAssemblyTypes(RepositoryServices).AsImplementedInterfaces(); #endregion #region 在控制器中使用属性依赖注入,其中注入属性必须标注为public //public ITestServiceE _testService {get;set } //注意 上方为属性注入 发现为Null 需要在Startup.cs 的 ConfigureServices 方法下加入如下代码 //services.AddControllers().AddControllersAsServices(); //在控制器中使用属性依赖注入,其中注入属性必须标注为public // var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes() //.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray(); // containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(); #endregion /// <summary> /// 当前使用 /// </summary> /// <param name="builder"></param> protected override void Load(ContainerBuilder builder) { //程序集范围注入 将匹配所有Service结尾的 builder.RegisterAssemblyTypes(typeof(SysUserService).Assembly) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces().PropertiesAutowired(); //单个注册 工作单元 和数据库上下文 builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().PropertiesAutowired(); builder.RegisterType<dbContext>().As<DbContext>().PropertiesAutowired(); //在控制器中使用属性依赖注入,其中注入属性必须标注为public 就是不需要通过构造函数 直接 //public ITestServiceE _testService {get;set } 可直接_testService.方法 不许在构造函数接收 //注意属性注入 发现为Null 需要在Startup.cs 的 ConfigureServices 方法下加入如下代码 //services.AddControllers().AddControllersAsServices(); var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes() .Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray(); builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(); } }
然后控制器通过构造函数注入,或者属性注入测试