-
AutoFac 具體使用知識總結
-
閱讀前提示 AutoFac 只是眾多IOC框架的其中一種, 比較主流的有
Unity
、autofac
、spring.net
、MEF
、Injection
、Asp.Net Core
的ServiceCollection
,等一些,還有一些,可能自己實現這一套東西。
1.為什么使用AutoFac? (自己的理解綜合所鏈接的因素)
- 傳說是速度最快的一個,輕量級性能高
- C#語言聯系很緊密,許多框架如Abp都會有默認支持AutoFac,微軟的Orchad開源程序使用的就是Autofac
- 支持很多的注入方式,除了傳統的 構造函數注入,DI容器注入(使用
IServiceProvider
接口的對象) 如方法注入,屬性注入,控制器注入 這些特殊的方式
2.缺點 - 傳說沒有微軟自帶的 依賴注入 速度快
AutoFac 幾種依賴注入使用方法介紹
-
演示絕大部分都是在 Startup.cs 里面進行的,也有一個測試的控制器
TestController
,重在理解,以下是自己研究的項目源碼GitHub地址: -
最基本的注入方式 通過DL容器的方式 一般的容器注入 初始
-
IServiceCollection serviceDescriptors = new ServiceCollection(); //指定關系 serviceDescriptors.AddScoped<ITestAService, TestAService>(); //build ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider(); //下面是作用域的關系比較 //1.同一個作用域 獲取的實例 時同一個 //var testA = (ITestAService)serviceProvider.GetService<ITestAService>(); //var testA1 = (ITestAService)serviceProvider.GetService<ITestAService>(); //var isEq = object.ReferenceEquals(testA, testA1); //2.再次Build時 范圍聲明周期 已經發生了變化 //ServiceProvider serviceProvider1 = serviceDescriptors.BuildServiceProvider(); //var testA2 = (ITestAService)serviceProvider1.GetService<ITestAService>(); //var isEq1 = object.ReferenceEquals(testA1, testA2); //testA.show();
-
-
AutoFac容器最簡單的使用
-
//容器構建着 ContainerBuilder containerBuilder = new ContainerBuilder(); //指定關系 containerBuilder.RegisterType<TestAService>().As<ITestAService>(); //構建 IContainer container = containerBuilder.Build(); //獲取服務 ITestAService testA3 = container.Resolve<ITestAService>(); testA3.show();
-
-
AutoFac容器 默認支持構造函數注入
-
ContainerBuilder containerBuilder1 = new ContainerBuilder(); containerBuilder1.RegisterType<TestAService>().As<ITestAService>(); containerBuilder1.RegisterType<TestBService>().As<ITestBService>(); IContainer container1 = containerBuilder1.Build(); ITestBService testB = container1.Resolve<ITestBService>(); testB.show();
-
-
AutoFac容器 屬性注入 PropertiesAutowired()
-
ContainerBuilder containerBuilder2 = new ContainerBuilder(); containerBuilder2.RegisterType<TestAService>().As<ITestAService>(); containerBuilder2.RegisterType<TestBService>().As<ITestBService>(); //支持屬性注入的方法 containerBuilder2.RegisterType<TestCService>().As<ITestCService>().PropertiesAutowired(); IContainer container2 = containerBuilder2.Build(); ITestCService testC = container2.Resolve<ITestCService>(); testC.show();
-
-
AutoFac 支持的方法注入
-
ContainerBuilder containerBuilder3 = new ContainerBuilder(); containerBuilder3.RegisterType<TestAService>().As<ITestAService>(); containerBuilder3.RegisterType<TestBService>().As<ITestBService>(); //支持屬性注入的方法 containerBuilder3.RegisterType<TestCService>().As<ITestCService>().PropertiesAutowired(); //方法注入 //其中的SetSevice()方法是在 TestDService里面定義的一個方法 containerBuilder3.RegisterType<TestDService>().OnActivated(a => a.Instance.SetSevice(a.Context.Resolve<ITestAService>())).As<ITestDService>(); //使用 IContainer container3 = containerBuilder3.Build(); ITestDService testD = container3.Resolve<ITestDService>(); testD.show();
-
-
AutoFac 聲明周期 瞬時(每次獲取對象都是一個全新的實例) 示例
-
ContainerBuilder containerBuilder4 = new ContainerBuilder(); containerBuilder4.RegisterType<TestAService>().As<ITestAService>().InstancePerRequest(); //InstancePerDependency 瞬時 //InstancePerLifetimeScope() 范圍 // InstancePerMatchingLifetimeScope("name名稱") *匹配 name* 聲明周期范圍實例 //SingleInstance 單例 //InstancePerRequest 每一個請求,一個實例 IContainer container4 = containerBuilder4.Build(); ITestAService testA4 = container4.Resolve<ITestAService>(); ITestAService testA5 = container4.Resolve<ITestAService>(); //比較 var IsEq = object.ReferenceEquals(testA4, testA5); Console.WriteLine(IsEq);
-
AutoFac 特殊的控制器中使用 屬性注入方式
-
需要使用兩個特性來實現
-
-
CustomPropertyAttribute 特性用來 當作標識,且聲明只能是屬性才能使用該特性
-
CustomPropertySelector 特性是需要給控制器告知哪些屬性是可以注入的 (需要一個判斷的維度)
-
具體代碼詳見 GitHub 示例
-
-
整個項目 使用AutoFac 自動構建 關系
-
方式一 使用 配置文件 (完全斷開對 實體的依賴)
- 安裝 支持的Nuget包
- Autofac.Extensions.DependencyInjection
- Autofac.Configuration
- 內部好像也是用來反射
Dll
來實現,感覺配置文件也挺復雜,所以就沒有使用這種方案
- 安裝 支持的Nuget包
-
方式二 使用用反射來實現 ******
-
1.收錢 需要在ConfigureServices 里面提供 控制器注入的支持
-
//AutoFac 提供控制器支持 //1 替換控制器的替換規則 //1.1 可以指定控制器讓 容器來創建 services.Replace(ServiceDescriptor.Transient<IControllerActivator,ServiceBasedControllerActivator>());
-
需要實現自定義實現
ConfigureContainer
方法,注意反射注入的方法需要寫在這里面,不然沒有效果-
代碼如下
-
/// <summary> /// AutoFac 自己會調用這個方法 進行注冊 /// 1.負責注冊 各種服務 /// 2.ServiceCollection 注冊的,也同樣是可以使用的 /// 3.還支持控制器 里面的屬性注入 /// </summary> /// <param name="builder"></param> public void ConfigureContainer(ContainerBuilder builder) { Assembly serviceDLL = Assembly.Load(new AssemblyName("WebApplicationApi")); //1.Service 后綴類的反射 注入 var serviceTypes = serviceDLL.GetTypes().Where(t => t.Name.EndsWith("Service") && !t.GetTypeInfo().IsAbstract); foreach (var serviceType in serviceTypes) { //var asdfasf = serviceType.Name; foreach (var interType in serviceType.GetInterfaces()) { var sname = serviceType.Name; var Iname = interType.Name; Console.WriteLine($"{sname}--->{Iname}"); builder.RegisterType(serviceType).As(interType).InstancePerDependency() .AsImplementedInterfaces()//自動以其實現的所有接口類型暴露(包括IDisposable接口) .InstancePerLifetimeScope() .PropertiesAutowired();//支持屬性注入的方法; } } //2 首先需要在Service,里面提供支持 services.Replace(.......) //2.1 控制器實例的注入 var controllerTypes = typeof(Startup).GetTypeInfo().Assembly.DefinedTypes. Where(x => x.IsClass && typeof(ControllerBase).GetTypeInfo().IsAssignableFrom(x)). Select(x => x.AsType()). ToArray(); builder.RegisterTypes(controllerTypes) //支持屬性注入的方法; //CustomPropertySelector 設置哪些是可以被注入的 (指定特性屬性注入的支持) .PropertiesAutowired(new CustomPropertySelector()); }
-
-
-
這樣就能直接在控制里面使用了
- 具體使用如下
- 具體使用如下
-
-