注冊組件
通過容器構造器ContainerBuilder注冊組件的三種方式:
-
通過類型反射注冊
-
通過現存實例注冊(實現對象的實例)
-
lambda表達式注冊(通過可實例化對象的匿名函數注冊)
每個組件可暴露一個或多個服務,通過ContainerBuilder中的As()方法組裝
// 創建注冊組件/服務的構建器。 var builder = new ContainerBuilder(); // 通過類型反射注冊 builder.RegisterType<ConsoleLogger>().As<ILogger>(); // 通過實例對象注冊 var output = new StringWriter(); builder.RegisterInstance(output).As<TextWriter>(); // 通過創建實例對象的lambda表達式注冊 builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>(); // 通過容器構造器ContainerBuilder創建容器 // 准備對象解析 var container = builder.Build(); // 你現在可以通過 Autofac去解析服務.比如, //此行代碼將解析並獲取(執行注冊的lambda表達式注冊的那個)服務的依賴實例reader using(var scope = container.BeginLifetimeScope()) { var reader = scope.Resolve<IConfigReader>(); }
反射組件
按類型注冊
通過反射生成的組件通常按類型注冊
//創建容器生成器 var builder = new ContainerBuilder(); //通過反射注冊的兩種寫法 builder.RegisterType<ConsoleLogger>(); builder.RegisterType(typeof(ConfigReader));
當使用基於反射的組件時,Autofac 會自動為您的類使用構造函數,其中包含能夠從容器中獲取的最多參數。
例如,假設您有一個包含三個構造函數的類,如下所示:
public class MyComponent { public MyComponent() { Console.WriteLine("無參構造方法被調用"); } public MyComponent(InterfaceTestA testA) { Console.WriteLine("第一個方法A被調用"); } public MyComponent(InterfaceTestA testA, InterfaceTestB testB) { Console.WriteLine("方法A、B都被調用"); } public void test() { Console.WriteLine("方法Test被調用"); } }
現在假設您在容器中注冊組件和服務,如下所示:
static void Main(string[] args) { var build = new ContainerBuilder(); build.RegisterType<EntityImpA>().As<InterfaceTestA>(); build.RegisterType<EntityImpB>().As<InterfaceTestB>(); build.RegisterType<MyComponent>(); Console.WriteLine("Hello World!"); var containner = build.Build(); using (var scope = containner.BeginLifetimeScope()) { //用生命周期作用域解析獲取IDateWriter對應的依賴對象實例 var writer = scope.Resolve<MyComponent>(); writer.test(); } }
當您解析您的組件cope.Resolve<MyComponent>()時,Autofac 將看到您已EntityImpA、EntityImpB注冊,在這種情況下,將選擇第三個構造函數
public MyComponent(InterfaceTestA testA, InterfaceTestB testB) { Console.WriteLine("方法A、B都被調用"); }
假設您在容器中注冊組件和服務,如下所示:
static void Main(string[] args) { var build = new ContainerBuilder(); build.RegisterType<EntityImpA>().As<InterfaceTestA>(); //build.RegisterType<EntityImpB>().As<InterfaceTestB>(); build.RegisterType<MyComponent>(); Console.WriteLine("Hello World!"); var containner = build.Build(); using (var scope = containner.BeginLifetimeScope()) { //用生命周期作用域解析獲取IDateWriter對應的依賴對象實例 var writer = scope.Resolve<MyComponent>(); writer.test(); } }
當您解析您的組件cope.Resolve<MyComponent>()時,Autofac 將看到您已EntityImpA注冊,EntityImpB沒注冊在這種情況下,將選擇第二個構造函數
public MyComponent(InterfaceTestA testA) { Console.WriteLine("第一個方法A被調用");因為它是容器中可以找到的參數最多的構造函數。
基於反射的組件的重要說明:您注冊的任何組件類型都RegisterType
必須是具體類型
指定構造函數
也可以通過一個特定的構造函數來使用和重寫這種自動選擇的構造方法,通過UsingConstructor方法和一系列表示構造函數中參數類型的參數列表注冊你的組件
builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));
請注意,您仍需要在解析時提供必要的參數,否則在嘗試解析對象時會出現錯誤。您可以在注冊時傳遞參數,也可以在解析時傳遞參數。
此時解析時會走的構造方法是public MyComponent(ILogger logger, IConfigReader reader) { /* ... */ }