AutoFac 生命週期管理
阿新 • • 發佈:2021-01-05
public void ConfigureContainer(ContainerBuilder containerBuilder) { #region 指定控制器由AutoFac 進行例項獲取 var assembly = this.GetType().GetTypeInfo().Assembly; var builder = new ContainerBuilder(); //新建Mvc管理程式集填入當前程式集 var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new AssemblyPart(assembly)); manager.FeatureProviders.Add(new ControllerFeatureProvider()); var feature = new ControllerFeature(); manager.PopulateFeature(feature); //建立單例並且允許屬性注入 builder.RegisterType<ApplicationPartManager>().AsSelf().SingleInstance(); builder.RegisterTypes(feature.Controllers.Select(t => t.AsType()).ToArray()).PropertiesAutowired(); #endregion //瞬時生命週期 每次獲取例項不一樣 containerBuilder.RegisterType<ServiceA>().As<IServiceA>().InstancePerDependency(); //單例 整個容器獲取例項都是同一個 containerBuilder.RegisterType<ServiceB>().As<IServiceB>().SingleInstance(); //作用域生命週期 只有在相同作用域下獲取到的服務例項才相同 containerBuilder.RegisterType<ServiceC>().As<IServiceC>().InstancePerLifetimeScope(); //匹配作用域生命週期 精確到某個作用域 containerBuilder.RegisterType<ServiceD>().As<IServiceD>().InstancePerMatchingLifetimeScope("MyScope"); //某個請求生命週期 不同請求獲取的服務例項不一樣 containerBuilder.RegisterType<ServiceE>().As<IServiceE>().InstancePerRequest(); // 隱式關聯型別建立巢狀的生命週期範圍 containerBuilder.RegisterType<ServiceG>().InstancePerOwned<IServiceF>(); containerBuilder.RegisterType<ServiceF>().Keyed<IServiceF>("ServiceF1"); var container = containerBuilder.Build(); var serviceA1 = container.Resolve<IServiceA>(); var serviceA2 = container.Resolve<IServiceA>(); Console.WriteLine("ServiceA1 和 serviceA2 是否相同" +ReferenceEquals(serviceA1,serviceA2)); var serviceB1 = container.Resolve<IServiceB>(); var serviceB2 = container.Resolve<IServiceB>(); Console.WriteLine("ServiceB1 和 serviceB2 是否相同" + ReferenceEquals(serviceB1, serviceB2)); using var scope1 = container.BeginLifetimeScope("scope1"); var serviceC1 = scope1.Resolve<IServiceC>(); var serviceC2 = scope1.Resolve<IServiceC>(); Console.WriteLine("ServiceC1 和 serviceC2 是否相同" + ReferenceEquals(serviceC1, serviceC2)); using var scope2 = container.BeginLifetimeScope("scope2"); var serviceC3 = scope2.Resolve<IServiceC>(); Console.WriteLine("ServiceC1 和 serviceC3 是否相同" + ReferenceEquals(serviceC1, serviceC3)); scope1.Dispose(); scope2.Dispose(); using var myScope = container.BeginLifetimeScope("MyScope"); var serviceD1 = myScope.Resolve<IServiceD>(); var serviceD2 = myScope.Resolve<IServiceD>(); Console.WriteLine("ServiceD1 和 serviceD2 是否相同" + ReferenceEquals(serviceD1, serviceD2)); var serviceF1 = myScope.ResolveKeyed<Owned<IServiceF>>("ServiceF1"); serviceF1.Value.Call(); serviceF1.Value.Call2(); }
- InstancePerDependency() 瞬時生命週期 每次獲取例項不一樣
- SingleInstance() 單例 整個容器獲取例項都是同一個
- InstancePerLifetimeScope() 作用域生命週期 只有在相同作用域下獲取到的服務例項才相同
- InstancePerMatchingLifetimeScope("MyScope") 匹配作用域生命週期 精確到某個作用域
- InstancePerRequest() 某個請求生命週期 不同請求獲取的服務例項不一樣
以上5點就不細說了,有很多詳細的教程和解讀了。關鍵來看最後一個,主要程式碼抽取出來
{ containerBuilder.RegisterType<ServiceG>().InstancePerOwned<IServiceF>(); containerBuilder.RegisterType<ServiceF>().Keyed<IServiceF>("ServiceF1"); var serviceF1 = myScope.ResolveKeyed<Owned<IServiceF>>("ServiceF1"); serviceF1.Value.Call(); serviceF1.Value.Call2(); } { public class ServiceF : IServiceF { public ServiceF(ServiceG serviceG) { ServiceG = serviceG; Console.WriteLine(this.GetType().Name+"已經被初始化"); } public ServiceG ServiceG { get;} public void Call() { Console.WriteLine(this.GetType().Name + "Call"); } public void Call2() { ServiceG.Call(); } } } { public class ServiceG:IServiceG { public void Call() { Console.WriteLine(this.GetType().Name + "Call"); } public ServiceG() { Console.WriteLine(this.GetType().Name + "已經被初始化"); } } }
執行結果如下
呼叫順序是ServiceG先被初始化,然後是初始化ServiceF。ServiceG和ServiceF的生命週期應該是相同的。
個人理解如下
containerBuilder.RegisterType<ServiceG>().InstancePerOwned<IServiceF>(); 這行程式碼將ServiceG的生命週期限定在了ServiceF的生命週期之下,如果提前釋放ServiceF的的生命週期,那麼ServiceG中的服務應該也無法使用。
但目前關於InstancePerOwned的文件並不多,而且很模糊。如果理解有誤,望大佬指教一下。