日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Autofac详解

發(fā)布時(shí)間:2023/12/29 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Autofac详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Autofac詳解

零、文章目錄

一、Autofac詳解

1、概述

  • Autofac是第三方IOC容器,是當(dāng)前最流行的IOC容器。
  • 功能強(qiáng)大,比asp.netcore內(nèi)置容器強(qiáng)大得多,支持屬性注入和方法注入,支持AOP。
  • 官網(wǎng)地址:http://autofac.org/
  • 源碼下載地址:https://github.com/autofac/Autofac

2、快速開始

(1)Nuget引入程序包

Autofac 基于版本6.3演示,Net5

(2)容器創(chuàng)建對(duì)象

//創(chuàng)建一個(gè)容器建造者 ContainerBuilder containerBuilder = new ContainerBuilder(); //注冊(cè)普通類 containerBuilder.RegisterType<Honer>(); //build一下,得到一個(gè)容器 IContainer container = containerBuilder.Build(); //可以基于容器來獲取對(duì)象的實(shí)例 Honer phone = container.Resolve<Honer>();

3、注冊(cè)的類型

(1)注冊(cè)普通類

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>(); IContainer container = containerBuilder.Build(); Honer phone = container.Resolve<Honer>();

(2)注冊(cè)抽象與實(shí)現(xiàn)

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>(); IContainer container = containerBuilder.Build(); IPhone phone = container.Resolve<IPhone>();

(3)注冊(cè)程序集

  • RegisterAssemblyTypes(程序集數(shù)組),程序集必須是public的
  • AsImplementedInterfaces():表示注冊(cè)的類型,以接口的方式注冊(cè)
  • PropertiesAutowired():支持屬性注入
  • Where:滿足條件類型注冊(cè)
var basePath = AppContext.BaseDirectory; var dll = Path.Combine(basePath, "MyAutofac.dll"); ContainerBuilder containerBuilder = new ContainerBuilder(); var assemblysServices = Assembly.LoadFrom(dll); containerBuilder.RegisterAssemblyTypes(assemblysServices).Where(t => !t.Name.EndsWith("XXX")).AsImplementedInterfaces().PropertiesAutowired(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve<ITeacher>();

4、三種注入方式

(1)構(gòu)造函數(shù)注入

默認(rèn)支持,無法用特性進(jìn)行篩選,默認(rèn)選參數(shù)最多的構(gòu)造函數(shù)進(jìn)行注入

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>(); containerBuilder.RegisterType<Teacher>().As<ITeacher>(); containerBuilder.RegisterType<Student>().As<IStudent>(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve<ITeacher>();

(2)全部屬性注入

關(guān)鍵詞PropertiesAutowired,這個(gè)對(duì)象所有屬性全部注入

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>(); containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired(); containerBuilder.RegisterType<Student>().As<IStudent>(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve<ITeacher>();

(3)標(biāo)記特性的屬性注入

關(guān)鍵詞PropertiesAutowired,定義特性選擇器CustomPropertySelector

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>(); containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired(new CustomPropertySelector()); containerBuilder.RegisterType<Student>().As<IStudent>(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve<ITeacher>(); public class CustomPropertySelector : IPropertySelector {public bool InjectProperty(PropertyInfo propertyInfo, object instance){var flag = propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(SelectPropAttribute));return flag;} }

(4)方法注入

關(guān)鍵詞OnActivated,指定調(diào)用方法

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>(); containerBuilder.RegisterType<Teacher>().As<ITeacher>().OnActivated(p =>{p.Instance.SetStudent1(p.Context.Resolve<IStudent>());}); containerBuilder.RegisterType<Student>().As<IStudent>(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve<ITeacher>();

5、對(duì)象生命周期

(1)瞬時(shí)生命周期

每次獲取都是全新的實(shí)例,關(guān)鍵詞InstancePerDependency,默認(rèn)的生命周期

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerDependency(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve<IPhone>(); IPhone phone2 = container.Resolve<IPhone>(); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerDependency:phone1==phone2=>{isflg1}"); InstancePerDependency:phone1==phone2=>False

(2)單例生命周期

同一個(gè)進(jìn)程內(nèi)都是同一個(gè)實(shí)例,關(guān)鍵詞SingleInstance

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().SingleInstance(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve<IPhone>(); IPhone phone2 = container.Resolve<IPhone>(); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"SingleInstance:phone1==phone2=>{isflg1}"); using (var scope = container.BeginLifetimeScope()) {IPhone phone3 = scope.Resolve<IPhone>();IPhone phone4 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone3, phone4);Console.WriteLine($"SingleInstance:phone3==phone4=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone3);Console.WriteLine($"SingleInstance:phone1==phone3=>{isflg3}"); } SingleInstance:phone1==phone2=>True SingleInstance:phone3==phone4=>True SingleInstance:phone1==phone3=>True

(3)作用域生命周期

同一個(gè)作用域內(nèi)都是同一個(gè)實(shí)例,關(guān)鍵詞InstancePerLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerLifetimeScope(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve<IPhone>(); IPhone phone2 = container.Resolve<IPhone>(); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerLifetimeScope:phone1==phone2=>{isflg1}"); IPhone phone3 = null; IPhone phone4 = null; using (var scope = container.BeginLifetimeScope()) {phone3 = scope.Resolve<IPhone>();phone4 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone3, phone4);Console.WriteLine($"InstancePerLifetimeScope:phone3==phone4=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone3);Console.WriteLine($"InstancePerLifetimeScope:phone1==phone3=>{isflg3}"); } IPhone phone5 = null; IPhone phone6 = null; using (var scope = container.BeginLifetimeScope()) {phone5 = scope.Resolve<IPhone>();phone6 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone5, phone6);Console.WriteLine($"InstancePerLifetimeScope:phone5==phone6=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone5);Console.WriteLine($"InstancePerLifetimeScope:phone1==phone5=>{isflg3}"); } bool isflg4 = object.ReferenceEquals(phone3, phone5); Console.WriteLine($"InstancePerLifetimeScope:phone3==phone5=>{isflg4}"); InstancePerLifetimeScope:phone1==phone2=>True InstancePerLifetimeScope:phone3==phone4=>True InstancePerLifetimeScope:phone1==phone3=>False InstancePerLifetimeScope:phone5==phone6=>True InstancePerLifetimeScope:phone1==phone5=>False InstancePerLifetimeScope:phone3==phone5=>False

(4)作用域范圍生命周期

在作用域范圍外無法創(chuàng)建實(shí)例,在作用域范圍里面,同一個(gè)作用域下面的對(duì)象是同一個(gè),關(guān)鍵詞InstancePerMatchingLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerMatchingLifetimeScope("scope1", "scope2"); IContainer container = containerBuilder.Build(); IPhone phone1 = null; IPhone phone2 = null; using (var scope = container.BeginLifetimeScope("scope1")) {phone1 = scope.Resolve<IPhone>();phone2 = scope.Resolve<IPhone>();bool isflg1 = object.ReferenceEquals(phone1, phone2);Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone2=>{isflg1}"); } IPhone phone3 = null; using (var scope = container.BeginLifetimeScope("scope2")) {phone3 = scope.Resolve<IPhone>(); } IPhone phone4 = null; using (var scope = container.BeginLifetimeScope("scope2")) { phone4 = scope.Resolve<IPhone>(); } bool isflg2 = object.ReferenceEquals(phone3, phone4); Console.WriteLine($"InstancePerMatchingLifetimeScope:phone3==phone4=>{isflg2}"); bool isflg3 = object.ReferenceEquals(phone1, phone3); Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone3=>{isflg3}"); InstancePerMatchingLifetimeScope:phone1==phone2=>True InstancePerMatchingLifetimeScope:phone3==phone4=>False InstancePerMatchingLifetimeScope:phone1==phone3=>False

(5)一次請(qǐng)求同一個(gè)對(duì)象

關(guān)鍵詞InstancePerRequest,只能在web項(xiàng)目中調(diào)試,控制臺(tái)報(bào)錯(cuò)

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerRequest(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve<IPhone>(); IPhone phone2 = container.Resolve<IPhone>(); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerRequest:phone1==phone2=>{isflg1}");

6、支持配置文件注冊(cè)

(1)nuget引入程序集

Autofac Autofac.Configuration Microsoft.Extensions.Configuration.Json

(2)配置文件autofac.json,屬性->始終復(fù)制

{"components": [{//實(shí)現(xiàn)"type": "Net5.IOC.Honer,Net5.IOC",//抽象"services": [{"type": "Net5.IOC.IPhone,Net5.IOC"}],//生命周期"instanceScope": "single-instance",//屬性注入 "injectProperties": true}] }

(3)通過配置文件注冊(cè)創(chuàng)建對(duì)象

ContainerBuilder containerBuilder = new ContainerBuilder(); IConfigurationBuilder config = new ConfigurationBuilder(); IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource() {Path = "Autofac/autofac.json",Optional = false,//boolean,默認(rèn)就是false,可不寫ReloadOnChange = true,//同上 }; config.Add(autofacJsonConfigSource); ConfigurationModule module = new ConfigurationModule(config.Build()); containerBuilder.RegisterModule(module); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve<IPhone>(); IPhone phone2 = container.Resolve<IPhone>(); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"配置文件注冊(cè):phone1==phone2=>{isflg1}");

(4)運(yùn)行結(jié)果

配置文件注冊(cè):phone1==phone2=>True

7、支持AOP切面編程

可以在不修改方法的前提下,在方法前后添加公共邏輯,日志,異常,緩存等

(1)nuget引入程序集

Castle.Core Autofac.Extras.DynamicProxy

(2)自定義一個(gè)切面類實(shí)現(xiàn)IInterceptor接口

public class CustomInterceptor : IInterceptor {public void Intercept(IInvocation invocation){Console.WriteLine("方法執(zhí)行前。。。");//執(zhí)行當(dāng)前方法invocation.Proceed();Console.WriteLine("方法執(zhí)行后。。。");} }

(3)在抽象/實(shí)現(xiàn)類上添加特性標(biāo)記

[Intercept(typeof(CustomInterceptor))] public interface IPhone {string ShowName(); } //實(shí)現(xiàn)類虛方法 public class Honer : IPhone {public virtual string ShowName(){Console.WriteLine("Honer");return "Honer";} }

(4)在容器中注冊(cè)關(guān)系創(chuàng)建對(duì)象

  • EnableInterfaceInterceptors + 特性標(biāo)記在抽象上,所有實(shí)現(xiàn)類都支持AOP
  • EnableInterfaceInterceptors + 特性標(biāo)記到實(shí)現(xiàn)類上,標(biāo)記的類就支持AOP
  • EnableClassInterceptors,要支持AOP的方法必須要是用virtual虛方法
  • EnableClassInterceptors + 特性標(biāo)記在抽象上,所有實(shí)現(xiàn)類都支持AOP
  • EnableClassInterceptors + 特性標(biāo)記到實(shí)現(xiàn)類上,標(biāo)記的類就支持AOP
ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().As<IPhone>().EnableInterfaceInterceptors(); containerBuilder.RegisterType(typeof(CustomInterceptor)); IContainer container = containerBuilder.Build(); IPhone phone = container.Resolve<IPhone>(); phone.ShowName();

(5)運(yùn)行結(jié)果

方法執(zhí)行前。。。 Honer 方法執(zhí)行后。。。

8、單抽象多實(shí)現(xiàn)問題

(1)在容器中注冊(cè)關(guān)系創(chuàng)建對(duì)象

注冊(cè)的時(shí)候不標(biāo)記名字,后注冊(cè)的會(huì)覆蓋先注冊(cè)的
注冊(cè)的時(shí)候標(biāo)記下名字,創(chuàng)建對(duì)象的時(shí)候用名稱來區(qū)分

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<Honer>().Named<IPhone>("Honer"); containerBuilder.RegisterType<Huawei>().Named<IPhone>("Huawei"); IContainer container = containerBuilder.Build(); IPhone honer = container.ResolveNamed<IPhone>("Honer"); IPhone huawei = container.ResolveNamed<IPhone>("Huawei"); honer.ShowName(); huawei.ShowName();

(2)運(yùn)行結(jié)果

Honer Huawei

9、集成到Asp.NetCore5框架

(1)nuget引入程序集

Autofac Autofac.Extensions.DependencyInjection

(2)定義實(shí)現(xiàn)類和抽象

public class UserService : IUserService { private IUserRepository UserRepositoryCtor { get; set; }public UserService(IUserRepository userRepository){UserRepositoryCtor = userRepository;} public string Login(string username, string password){return "登錄成功";} }

(3)添加控制器和頁(yè)面

public class FourthController : Controller {private IUserService _userService;public FourthController(IUserService userService){this._userService = userService;}public IActionResult Index(){object result = this._userService.Login("username", "password");return View(result);} } @model String <h2>this is fourth index...</h2> <h2>@Model</h2>

(4)在Program替換容器工廠

public class Program {public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).UseServiceProviderFactory(new AutofacServiceProviderFactory()); }

(5)在Startup類的ConfigureServices方法中替換創(chuàng)建控制器的類

//控制器默認(rèn)是有IControllerActivator創(chuàng)建的,替換成由容器創(chuàng)建 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

(6)注冊(cè)抽象和實(shí)現(xiàn)的關(guān)系

在Startup類中專門增加一個(gè)方法ConfigureContainer,用于注冊(cè)抽象和實(shí)現(xiàn),可以把這些注冊(cè)信息進(jìn)行模塊化封裝到AutofacModule

當(dāng)抽象類和實(shí)現(xiàn)非常多的時(shí)候,可以將整個(gè)dll注冊(cè),特殊的關(guān)系可以寫在后面覆蓋前面的注冊(cè)關(guān)系。

/// <summary> /// Autofac專用:注冊(cè)抽象和細(xì)節(jié)之間的關(guān)系,使用autofac后原來內(nèi)置注冊(cè)的關(guān)系要注釋掉 /// Autofac和ServiceCollection是二者并存的,Autofac會(huì)接管ServiceCollection的一切 /// </summary> /// <param name="builder"></param> public void ConfigureContainer(ContainerBuilder builder) {builder.RegisterModule<AutofacModule>(); } public class AutofacModule : Module {/// <summary>/// 重寫Autofac管道中的Load方法,在這里注入注冊(cè)的內(nèi)容/// </summary>/// <param name="builder"></param>protected override void Load(ContainerBuilder builder){//注冊(cè)抽象與實(shí)現(xiàn)builder.RegisterType<UserRepository>().As<IUserRepository>();builder.RegisterType<UserService>().As<IUserService>();//注冊(cè)所有控制器類var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes().Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();//實(shí)現(xiàn)屬性注入,這邊無法實(shí)現(xiàn)方法注入builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();} }

(7)運(yùn)行結(jié)果

(8)在Startup的Configure方法中用容器創(chuàng)建對(duì)象

using (var container = host.Services.CreateScope()) {IUserService userService = container.ServiceProvider.GetService<IUserService>(); }

(9)單抽象多實(shí)現(xiàn)集成到框架

注入的時(shí)候通過構(gòu)造函數(shù)或者屬性注入autofac上下文實(shí)例,再根據(jù)名稱創(chuàng)建對(duì)應(yīng)實(shí)例。

定義單抽象和多實(shí)例類

//抽象 public interface ITestService {string Show(); } //實(shí)現(xiàn)1 public class TestServiceA : ITestService {public string Show(){return "TestServiceA";} } //實(shí)現(xiàn)2 public class TestServiceB : ITestService {public string Show(){return "TestServiceB";} }

在AutofacModule注冊(cè)抽象和實(shí)現(xiàn)的關(guān)系

//單抽象多實(shí)現(xiàn)注冊(cè) builder.RegisterType<TestServiceA>().Named<ITestService>("a"); builder.RegisterType<TestServiceB>().Named<ITestService>("b");

添加控制器和頁(yè)面

public class FifthController : Controller {private IComponentContext _componentContext;public FifthController(IComponentContext componentContext){this._componentContext = componentContext;}public IActionResult Index(){ITestService testServiceA = _componentContext.ResolveNamed<ITestService>("a");ITestService testServiceB = _componentContext.ResolveNamed<ITestService>("b");object result = $"{testServiceA.Show()}--{testServiceB.Show()}";return View(result);} } @model String <h2>this is Fifth index...</h2> <h2>@Model</h2>

運(yùn)行結(jié)果

總結(jié)

以上是生活随笔為你收集整理的Autofac详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。