请选择 进入手机版 | 继续访问电脑版

[ASP.NET] .Net Core 之AutoFac的利用

[复制链接]
查看257 | 回复49 | 2021-9-15 07:24:21 | 显示全部楼层 |阅读模式
目次

本文不先容 IoC和DI的概念,假如 你对Ioc之前没有相识 的话,建议先去搜刮 一下干系 的资料

这篇文章将简单先容 一下AutoFac的基本利用 以及在asp .net core中的应用

Autofac先容

组件的三种注册方式

1.反射

2.现成的实例(new)

3.lambda表达式 (一个实行 实例化对象的匿名方法)

下面是一些简短的示例,我尽大概 多的列出来一些常用的注册方式,同时在解释 中表明 下“组件”、“服务”等一些名词的含义

  1. // 创建注册组件的builder
  2. var builder = new ContainerBuilder();
  3. //根据类型注册组件 ConsoleLogger 暴漏服务:ILogger
  4. builder.RegisterType<ConsoleLogger>().As<ILogger>();
  5. //根据类型注册组件 ConsoleLogger,暴漏其实现的所有服务(接口)
  6. builder.RegisterType<ConsoleLogger>().AsImplementedInterfaces();
  7. // 根据实例注册组件 output 暴漏服务:TextWriter
  8. var output = new StringWriter();
  9. builder.RegisterInstance(output).As<TextWriter>();
  10. //表达式注册组件,这里我们是在构造函数时传参->"musection" 暴漏服务:IConfigReader
  11. builder.Register(c =new ConfigReader("mysection")).As<IConfigReader>();
  12. //表达式注册组件,解析时传参
  13. var service = scope.Resolve<IConfigReader>(
  14. new NamedParameter("section", "mysection"));
  15. //反射注册组件,直接注册了ConsoleLogger类(必须是具体的类),如果ConsoleLogger有多个构造函数,将会取参数最多的那个构造函数进行实例化
  16. builder.RegisterType<ConsoleLogger>();
  17. //反射注册组件,手动指定构造函数,这里指定了调用 MyComponent(ILogger log,IConfigReader config)的构造函数进行注册
  18. builder.RegisterType<MyComponent>()
  19. .UsingConstructor(typeof(ILogger), typeof(IConfigReader));
  20. //注册MySingleton类中的静态变量"Instance",ExternallyOwned()函数指定自己控制实例的生命周期,而不是由autofac自动释放
  21. builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();
  22. //一个组件暴漏两个服务
  23. builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>();
  24. //注册当前程序集中以“Service”结尾的类
  25. builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
  26. //注册"MyApp.Repository"程序集中所有的类
  27. builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
  28. //构建一个容器完成注册
  29. var rootcontainer = builder.Build();
  30. //可以通过下面这种方式手动获取IConfigReader 的实现类
  31. //这种手动解析的方式需要 从生命周期作用域内获取组件,以保证组件最终被释放
  32. //不要直接从根容器rootcontainer中解析组件,很有可能会导致内存泄漏
  33. using(var scope = rootcontainer.BeginLifetimeScope())
  34. {
  35. var reader = scope.Resolve<IConfigReader>();
  36. }
复制代码

假如 不止一个组件暴露了雷同 的服务, Autofac将利用 末了 注册的组件作为服务的提供方。 想要覆盖这种举动 , 在注册代码后利用

  1. PreserveExistingDefaults()
复制代码
方法修改

生命周期

  1. [code]using(var scope = rootcontainer.BeginLifetimeScope())
复制代码
上面的这段代码创建了一个生命周期作用域 生命周期作用域是可开释 的,在作用域内分析 的组件肯定 要保证在using之内利用 或者末了 手动调用组件的Dispose()函数 避免引用类的生命周期大于被引用类的生命周期 :如service 引用 repository 假如 service的生命周期为单例,repository的生命周期为perrequest。service不会开释 ,以是 终极 会造成干系 的repository始终无法开释 的环境 (Captive Dependencies) 固然 我们必要 尽大概 的避免直接从根容器分析 组件,但总有破例 的环境 ,对于非单例的组件,肯定 不要忘记调用组件的Dispose函数,实际 上对于非单例的组件,从项目架构上来说,理论上应该是从构造函数注入进去的而不是手动分析 。 必要 手动分析 的应该为一些设置 帮助类等[/code]

对于一个详细 组件(类)的生命周期分为以下几种(后面的函数是autofac对应的函数):

  1. <ul>
  2. <li>每个依赖一个实例(Instance Per Dependency) (默认) ----InstancePerDependency()</li>
  3. <li>单一实例(Single Instance) 单例 ----SingleInstance()</li>
  4. <li>每个生命周期作用域一个实例(Instance Per Lifetime Scope)----InstancePerLifetimeScope()</li>
  5. <li>每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)----InstancePerMatchingLifetimeScope()</li>
  6. <li>每个请求一个实例(Instance Per Request) asp.net web请求----InstancePerRequest()</li>
  7. <li>每次被拥有一个实例(Instance Per Owned) ----InstancePerOwned()</li>
  8. </ul>
复制代码

假如 你从前 在传统的ASP.NET MVC项目中用过autofac,必要 留意 一些区别:

  1. <ul>
  2. <li>.net Core中需要使用[code]InstancePerLifetimeScope
复制代码
替换 之前(传统asp.net)的
  1. InstancePerRequest
复制代码
,保证每次HTTP哀求 只有唯一的依赖 实例被创建。
  1. InstancePerRequest
复制代码
哀求 级别已经不存在了
  • .net Core中Web Api与Mvc的注册方式一样
  • .net Core中不再必要 注册控制器,控制器由.net core创建,不归autofac管理(除了控制器的构造函数),这也表明 了为什么不再利用
    1. InstancePerRequest
    复制代码
    生命周期,但是可以通过
    1. AddControllersAsServices()
    复制代码
    函数改变,想要深入相识 的可以查看:https://www.strathweb.com/2016/03/the-subtle-perils-of-controller-dependency-injection-in-asp-net-core-mvc/
  • [/code]

    AutoFac 在asp .net core中的利用

    在.net core 中利用 autofac还是比较简单的,相比于传统的asp.net web 项目,省去了很多步骤

    引入nuget程序包:

    • Autofac
    • Autofac.Extensions.DependencyInjection

    startup 中代码:

    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. }
    复制代码
    1. 上面代码调用了builder的[code]RegisterModule
    复制代码
    函数,这个函数必要 传入一个
    1. TModule
    复制代码
    的泛型,称之为autofac的模块 模块的功能就是把全部 干系 的注册设置 都放在一个类中,使代码更易于维护和设置 ,下面展示了
    1. DefaultModuleRegister
    复制代码
    中的代码[/code]

    DefaultModuleRegister:

    1. public class DefaultModuleRegister : Module
    2. {
    3. protected override void Load(ContainerBuilder builder)
    4. {
    5. //注册当前程序集中以“Ser”结尾的类,暴漏类实现的所有接口,生命周期为PerLifetimeScope
    6. builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Ser")).AsImplementedInterfaces().InstancePerLifetimeScope();
    7. builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces().InstancePerLifetimeScope();
    8. //注册所有"MyApp.Repository"程序集中的类
    9. //builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
    10. }
    11. public static Assembly GetAssembly(string assemblyName)
    12. {
    13. var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(AppContext.BaseDirectory + $"{assemblyName}.dll");
    14. return assembly;
    15. }
    16. }
    复制代码

    Configure函数中可以选择性的加上程序克制 时Autofac的开释 函数:

    1. public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
    2. {
    3. if (env.IsDevelopment())
    4. {
    5. app.UseDeveloperExceptionPage();
    6. app.UseBrowserLink();
    7. }
    8. else
    9. {
    10. app.UseExceptionHandler("/Home/Error");
    11. }
    12. app.UseStaticFiles();
    13. app.UseMvc(routes =>
    14. {
    15. routes.MapRoute(
    16. name: "default",
    17. template: "{controller=Home}/{action=Index}/{id?}");
    18. });
    19. //程序停止调用函数
    20. appLifetime.ApplicationStopped.Register(() => { AutofacContainer.Dispose(); });
    21. }
    复制代码

    Controller中代码:

    1. private IUserSer _user;
    2. private IUserSer _user2;
    3. public HomeController(IUserSer user, IUserSer user2)
    4. {
    5. _user = user;
    6. _user2 = user2;
    7. }
    8. public IActionResult Index()
    9. {
    10. using (var scope = Startup.AutofacContainer.BeginLifetimeScope())
    11. {
    12. IConfiguration config = scope.Resolve<IConfiguration>();
    13. IHostingEnvironment env = scope.Resolve<IHostingEnvironment>();
    14. }
    15. string name = _user.GetName();
    16. string name2 = _user2.GetName();
    17. return View();
    18. }
    复制代码
    1. 可以看到,因为我们将IServiceCollection中的服务填充到了autofac中了,所以现在可以在任何位置通过AutoFac解析出来.net core默认注入的服务(IConfiguration,IHostingEnvironment等)了
    2. 正常项目使用中,我们应该将[code]AutofacContainer
    复制代码
    放在一个公共的类库中以便各个工程均可调用[/code]

    到此这篇关于.Net Core 之AutoFac的利用 的文章就先容 到这了,更多干系 .Net Core AutoFac内容请搜刮 脚本之家从前 的文章或继续欣赏 下面的干系 文章盼望 大家以后多多支持脚本之家!


    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
    回复

    使用道具 举报

    avatar 意乱了真假意wk | 2021-9-15 20:20:22 | 显示全部楼层
    太邪乎了吧?
    回复

    使用道具 举报

    avatar 敢想敢做敢拼 | 2021-9-16 15:17:18 | 显示全部楼层
    很给力!
    回复

    使用道具 举报

    avatar 嗅觉Y不缺失 | 2021-9-19 17:38:50 | 显示全部楼层
    吹牛的人越来越多了!
    回复

    使用道具 举报

    avatar 一品菊花茶酪 | 2021-9-21 19:38:01 | 显示全部楼层
    世界末日我都挺过去了,看到admin楼主我才知道为什么上帝留我到现在!
    回复

    使用道具 举报

    avatar 万胜 | 2021-9-21 22:15:38 | 显示全部楼层
    精华帖的节奏啊!
    回复

    使用道具 举报

    avatar 心灰意冷437 | 2021-9-21 22:15:41 | 显示全部楼层
    最近压力山大啊!
    回复

    使用道具 举报

    avatar 15155324777 | 2021-9-22 12:49:58 | 显示全部楼层
    好多兽医在广场上义诊,admin楼主去看看吧!
    回复

    使用道具 举报

    avatar Rudy64077 | 2021-10-3 18:41:17 | 显示全部楼层
    祖国尚未统一,我却天天灌水,好内疚!
    回复

    使用道具 举报

    avatar 哲911 | 2021-10-3 19:24:12 | 显示全部楼层
    楼上的说的很多!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则