侧边栏

NetCore使用Autofact入门

netCore3.1中应用Autofact

在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期.

微软给自行注入的服务,提供了3种生命周期.

Transient(瞬时的)

 每次请求时都会创建的瞬时生命周期服务。这个生命周期最适合轻量级,无状态的服务。

Scoped(作用域的)

在同作用域,服务每个请求只创建一次。

Singleton(唯一的)

全局只创建一次,第一次被请求的时候被创建,然后就一直使用这一个.

如何使用这三种生命周期呢?.我们直接在注入的时候用不同的方法就行了,代码如下:

1
2
3
services.AddTransient<ITestService, TestService>();
services.AddScoped<ITestService2, TestService2>();
services.AddSingleton<ITestService3, TestService3>();  

自带的IOC 做一些小的项目完全没有问题,但是大项目使用起来就比较单一,所以我们将默认的IOC容器替换为Autofac

.net core 2.x和3.x 使用autofac注入方式不一样,此文章是针对.net core 3.x

 首先,我们需要从nuget引用相关的包.

Autofac.Extensions.DependencyInjection(这个包扩展了一些微软提供服务的类.来方便替换autofac)

然后在Program.cs 新增一行代码

1
2
3
4
5
6
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                }).UseServiceProviderFactory(new AutofacServiceProviderFactory());

  

然后在Startup.cs 增加方法

1
2
3
4
public void ConfigureContainer(ContainerBuilder containerBuilder)
       {
           containerBuilder.RegisterModule<ConfigureAutofac>();
       }
1
ConfigureAutofac 是自己封装的一个类  继承了 Autofac.Module  也可以将以下代码直接写在这个方法里面:
复制代码
复制代码
 public class ConfigureAutofac : Autofac.Module
    {
        protected override void Load(ContainerBuilder containerBuilder)
        {
            //直接注册某一个类和接口
            //左边的是实现类,右边的As是接口
            //containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance();


            #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
            var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)).ToArray();
            containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
            #endregion
        }
    }
复制代码
复制代码

注:业务逻辑层每个类都以Service结尾 如下截图:

 

 然后控制器通过构造函数注入,或者属性注入测试 如下:

 

 蓝色框为属性注入  发现为Null  需要在Startup.cs  的 ConfigureServices 方法下加入如下代码

1
services.AddControllers().AddControllersAsServices(); //控制器当做实例创建

OK  结束  

看到好的博文记录一下:

https://www.cnblogs.com/diwu0510/p/11562248.html

AutoFac中的方法说明:

https://www.cnblogs.com/qtiger/p/13093739.html

 

Net6.0使用:

1. 引用NuGet包

Install-Package Autofac -Version 6.3.0
Install-Package Autofac.Extensions.DependencyInjection -Version 7.2.0

2. Program 中注册使用

2.1 普通注入

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder => {
    builder.RegisterType<A>().As<IA>();  // 直接注册某一个类和接口,左边的是实现类,右边的As是接口
});

2.2 反射程序集方式服务注册

builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
   var assemblysServices = Assembly.Load("Exercise.Services");
   containerBuilder.RegisterAssemblyTypes(assemblysServices)
              .AsImplementedInterfaces()
              .InstancePerLifetimeScope();
});

还可以进行选择性批量注入,注入之后通过 构造函数或者属性注入的方式使用。
.net core 3.1 使用autofac注入,不同点只在于 Program 中的注册方式。

3. AutoFac中常用方法说明

基本概念

1、AsImplementedInterfaces() 是以接口方式进行注入,注入这些类的所有的公共接口作为服务

2、InstancePerRequest() 每次请求共享同一个实例,使用ef时,使不同的操作使用同一个数据上下文

3、PreserveExistingDefaults() 如果不止一个组件暴露了相同的服务, Autofac将使用最后注册的组件作为服务的提供方,那么使用PreserveExistingDefaults防止后面注册的覆盖前面注册的

builder.Register<A>() .As<IA>();

builder.Register<AA>() .As<IA>();  // 这样AA就会覆盖A

builder.Register<AA>() .As<IA>().PreserveExistingDefaults(); // 这样A是IA的默认值,不会被AA覆盖   

4、InstancePerDependency为每个依赖或者调用(Resolve())都创建一个新的对象,唯一的实例

5、SingleInstance 为每次请求都使用同一个对象,单例模式.告诉容器,是个单例,但这个单例不用自己实现。

6、RegisterGeneric 对泛型类进行注册

builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>))

7、RegisterInstance() 注册一个实例,比如: 对已经存在的对象的实例进行注册,这样可以使实例转化为由容器托管的实例

8、RegisterControllers() 注册Controllers

builder.RegisterControllers(Assembly.GetExecutingAssembly()); // 注册当前程序集中的所有Controllers  

9、RegisterFilterProvider() 注册Filter过滤器

builder.RegisterFilterProvider()

10、RegisterAssemblyTypes 注册类

builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()); // 注册了当前程序集内的所有的类

11、InstancePerMatchingLifetimeScope 在一个做标识的生命周期域中,每一个依赖或调用创建一个单一的共享的实例。打了标识了的生命周期域中的子标识域中可以共享父级域中的实例

builder.RegisterType<A>() .AsImplementedInterfaces() .InstancePerMatchingLifetimeScope();

12、InstancePerHttpRequest在一次Http请求上下文中,共享一个组件实例。仅适用于asp.net mvc开发

13、InstancePerLifetimeScope在一个生命周期中,每一次的依赖组件或调用(Resolve())创建一个单一的共享的实例,且每一个不同的生命周期域,实例是不同的

14、UsingConstructor(参数) 自动装配,手动使用特定的构造函数

builder.RegisterType<A>().UsingConstructor(typeof(IA),typeof(IAA)); // 这样指定调用的是A(IA,IAA)的构造函数,如果该构造函数不存在则报错

15、[AsClosedTypesOf(open)]AsClosedTypesOf(typeof(IA<>)): 如果是多继承的话,注册的程序集所对应的服务(接口)是离这个类最近的开放的泛型实例(接口)

builder.RegisterAssemblyTypes(A).AsClosedTypesOf(typeof(IRepository<>));

Autofac中涉及的生命周期

//1、瞬时生命周期:注册之后,每次获取到的服务实例都不一样(默认的注册方式)
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();
//2、单例生命周期:整个容器中获取的服务实例都是同一个
containerBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance();
//3、作用域生命周期:在相同作用域下获取到的服务实例是相同的
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
//4、作用域生命周期:可以指定到某一个作用域,然后在相同作用域下共享服务实例
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerMatchingLifetimeScope("My");
//5、http请求上下文的生命周期:在一次Http请求上下文中,共享一个组件实例。仅适用于asp.net mvc开发。
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerRequest();
//6、拥有隐式关系类型的创建新的嵌套生命周期的作用域,在一个生命周期域中所拥有的实例创建的生命周期中,
//  每一个依赖组件或调用Resolve()方法创建一个单一的共享的实例,并且子生命周期域共享父生命周期域中的实例
containerBuilder.RegisterType<UserService>().InstancePerOwned<IUserService>(); 
posted @   我有我的骄傲  阅读(612)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
点击右上角即可分享
微信分享提示