隐藏

.netcore 利用 Autofac泛型依赖注入

发布:2022/1/17 22:46:35作者:管理员 来源:本站 浏览次数:733

什么是泛型依赖注入

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

如上图:
定义了两个泛型base类:BaseService和BaseRepository
对于UserService和UserRpository分别继承两个base类,泛型都是User,则他们俩继承了父类的依赖关系。
那么在.net core里面怎么实现泛型依赖注入呢
一、安装Autofac

先看项目结构

IMyRepository定义仓储接口

        public interface IMyRepository<T> where T: class
        {
            string GetTypeof();
        }

MyRepositoryBase仓储实现

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

CustomAutofacModule 公共的依赖注入类

        public class CustomAutofacModule : Module
        {
     
            public CustomAutofacModule(ContainerBuilder builder) {
               
            }
            /// <summary>
            /// AutoFac注册类
            /// </summary>
            /// <param name="builder"></param>
            protected override void Load(ContainerBuilder builder)
            {
                builder.RegisterGeneric(typeof(MyRepositoryBase<>)).As(typeof(IMyRepository<>)).InstancePerDependency();//注册仓储泛型
    //builder.RegisterGeneric(typeof(MyRepositoryBase<,>)).As(typeof(IMyRepository<,>)).InstancePerDependency();//注册仓储泛型 2个以上的泛型参数
             //  builder.RegisterType<myAssembly>().As<ImyAssembly>();   //普通依赖注入
            }
        }

在Program声明实现依赖注入

        public class Program
        {
            public static void Main(string[] args)
            {
     
                CreateHostBuilder(args).Build().Run();
            }
     
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    //改用Autofac来实现依赖注入
                    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }

修改Startup,运行时候触发CustomAutofacModule

        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
     
            public IConfiguration Configuration { get; }
            //autofac 新增
            public ILifetimeScope AutofacContainer { get; private set; }
     
            public void ConfigureServices(IServiceCollection services)
            {
     
                services.AddControllers();
     
     
            }
     
            public void ConfigureContainer(ContainerBuilder builder)
            {
                // 直接用Autofac注册我们自定义的
                builder.RegisterModule(new CustomAutofacModule(builder));
            }
     
          
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                //autofac 新增
                this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
     
     
                app.UseRouting();
     
                app.UseAuthorization();
     
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
        }

在Home控制器中使用

        [ApiController]
        [Route("[controller]")]
        public class HomeController : ControllerBase
        {
            //public IMyRepository<User> _UserServer { get; set; }
            private readonly IMyRepository<User> _UserServer;
            private readonly IMyRepository<Role> _RoleServer;
            public HomeController(IMyRepository<User> UserServer, IMyRepository<Role> RoleServer)
            {
                _UserServer = UserServer;
                _RoleServer = RoleServer;
            }
     
          
            [Route("Get")]
            public string Get() {
                return _UserServer.GetTypeof();//"user"; //
            }
          
            [Route("GetRole")]
            public string GetRole()
            {
                return _RoleServer.GetTypeof();//"role"; //
            }
     
        }

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

 

 
番外:

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

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

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

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

 

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

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

 DependencyLifeStyle.Transient 的作用

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

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

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

    public static IContainer AutofacContainer;
    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        //注册服务进 IServiceCollection
        services.AddMvc();
        ContainerBuilder builder = new ContainerBuilder();
        //将services中的服务填充到Autofac中.
        builder.Populate(services);
        //新模块组件注册
        builder.RegisterModule<DefaultModuleRegister>();
        //创建容器.
        AutofacContainer = builder.Build();
        //使用容器创建 AutofacServiceProvider
        return new AutofacServiceProvider(AutofacContainer);
    }