.netcore 利用 Autofac泛型依赖注入

墨蓝 2022-11-11 13:10 451阅读 0赞

什么是泛型依赖注入

创建两个带泛型的类,并配置两者的依赖关系,对于继承这两个类的子类,如果泛型相同,则会继承这种依赖关系:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5ncnVpNDA_size_16_color_FFFFFF_t_70

如上图:
定义了两个泛型base类:BaseService和BaseRepository
对于UserService和UserRpository分别继承两个base类,泛型都是User,则他们俩继承了父类的依赖关系。

那么在.net core里面怎么实现泛型依赖注入呢

一、安装Autofac

20190320232103489.png

先看项目结构

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5ncnVpNDA_size_16_color_FFFFFF_t_70 1

IMyRepository定义仓储接口

  1. public interface IMyRepository<T> where T: class
  2. {
  3. string GetTypeof();
  4. }

MyRepositoryBase仓储实现

  1. public class MyRepositoryBase<T> : IMyRepository<T> where T : class
  2. {
  3. public string GetTypeof()
  4. {
  5. return typeof(T).Name; //通过typeof可以知道泛型的名字
  6. }
  7. }

CustomAutofacModule 公共的依赖注入类

  1. public class CustomAutofacModule : Module
  2. {
  3. public CustomAutofacModule(ContainerBuilder builder) {
  4. }
  5. /// <summary>
  6. /// AutoFac注册类
  7. /// </summary>
  8. /// <param name="builder"></param>
  9. protected override void Load(ContainerBuilder builder)
  10. {
  11. builder.RegisterGeneric(typeof(MyRepositoryBase<>)).As(typeof(IMyRepository<>)).InstancePerDependency();//注册仓储泛型
  12. //builder.RegisterGeneric(typeof(MyRepositoryBase<,>)).As(typeof(IMyRepository<,>)).InstancePerDependency();//注册仓储泛型 2个以上的泛型参数
  13. // builder.RegisterType<myAssembly>().As<ImyAssembly>(); //普通依赖注入
  14. }
  15. }

在Program声明实现依赖注入

20210320145536845.png

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. //改用Autofac来实现依赖注入
  10. .UseServiceProviderFactory(new AutofacServiceProviderFactory())
  11. .ConfigureWebHostDefaults(webBuilder =>
  12. {
  13. webBuilder.UseStartup<Startup>();
  14. });
  15. }

修改Startup,运行时候触发CustomAutofacModule

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. public IConfiguration Configuration { get; }
  8. //autofac 新增
  9. public ILifetimeScope AutofacContainer { get; private set; }
  10. public void ConfigureServices(IServiceCollection services)
  11. {
  12. services.AddControllers();
  13. }
  14. public void ConfigureContainer(ContainerBuilder builder)
  15. {
  16. // 直接用Autofac注册我们自定义的
  17. builder.RegisterModule(new CustomAutofacModule(builder));
  18. }
  19. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  20. {
  21. if (env.IsDevelopment())
  22. {
  23. app.UseDeveloperExceptionPage();
  24. }
  25. //autofac 新增
  26. this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
  27. app.UseRouting();
  28. app.UseAuthorization();
  29. app.UseEndpoints(endpoints =>
  30. {
  31. endpoints.MapControllers();
  32. });
  33. }
  34. }

在Home控制器中使用

  1. [ApiController]
  2. [Route("[controller]")]
  3. public class HomeController : ControllerBase
  4. {
  5. //public IMyRepository<User> _UserServer { get; set; }
  6. private readonly IMyRepository<User> _UserServer;
  7. private readonly IMyRepository<Role> _RoleServer;
  8. public HomeController(IMyRepository<User> UserServer, IMyRepository<Role> RoleServer)
  9. {
  10. _UserServer = UserServer;
  11. _RoleServer = RoleServer;
  12. }
  13. [Route("Get")]
  14. public string Get() {
  15. return _UserServer.GetTypeof();//"user"; //
  16. }
  17. [Route("GetRole")]
  18. public string GetRole()
  19. {
  20. return _RoleServer.GetTypeof();//"role"; //
  21. }
  22. }

可以看到 不同的地方实现不同的对象

20210320150439765.png

20210320150540958.png

#

番外:

我是因为看到ABP框架的IRepository的实现才研究泛型依赖注入的用法的。

ABP框架吧Autofac已经 封装为IocManager 了

所以ABP框架不需要 引入Autofac框架。只需要在对应的XXXCoreModule 中的Initialize()方法声明依赖注入便可

  1. IocManager.Register(typeof(IMyRepository<>), typeof(MyRepositoryBase<>), DependencyLifeStyle.Transient);

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5ncnVpNDA_size_16_color_FFFFFF_t_70 2

如果是2个以上的泛型写法是

  1. IocManager.Register(typeof(IAmbientScopeProvider<,>), typeof(DataContextAmbientScopeProvider<,>), DependencyLifeStyle.Transient);

DependencyLifeStyle.Transient 的作用

Transient :瞬态,要么作用域是整个进程,要么作用域是一个请求,而这里的 Transient 就没有作用域概念了,注入一次 实例化一次 最明显的区别,属性注入是不可用的,只能构造函数注入

Singleton:可以在你的进程中保持着一个实例,也就是说仅有一次实例化 最明显的区别,属性注入是可用的

#

番外2:

看到了很多教程是不用声明CustomAutofacModule类的直接在Startup声明依赖注入就可以的。但是那是core 2.0的写法。core 3.0 下面的写法是会报错的

  1. public static IContainer AutofacContainer;
  2. // This method gets called by the runtime. Use this method to add services to the container.
  3. public IServiceProvider ConfigureServices(IServiceCollection services)
  4. {
  5. //注册服务进 IServiceCollection
  6. services.AddMvc();
  7. ContainerBuilder builder = new ContainerBuilder();
  8. //将services中的服务填充到Autofac中.
  9. builder.Populate(services);
  10. //新模块组件注册
  11. builder.RegisterModule<DefaultModuleRegister>();
  12. //创建容器.
  13. AutofacContainer = builder.Build();
  14. //使用容器创建 AutofacServiceProvider
  15. return new AutofacServiceProvider(AutofacContainer);
  16. }

发表评论

表情:
评论列表 (有 0 条评论,451人围观)

还没有评论,来说两句吧...

相关阅读

    相关 依赖注入

    纸上得来终觉浅 关于泛型依赖注入,只明白它的思想,考虑了整个下午都不明确它所应用的场合,暂时把用法记下来,后面再学习整理。使用示例如下: public class

    相关 Spring--依赖注入

    spring 4.x以上版本才有 创建两个带泛型的类,并配置两者的依赖关系,对于继承这两个类的子类,如果泛型相同,则会继承这种依赖关系: ![watermark_type