Autofac筆記5-屬性注入
| | | 0 | |
前面談過傳入建構參數,但並非所有物件參數都可由建構式傳入,有些要透過屬性指定(例如: new MyObject() { SomeProperty = SomeValue };),而這也是IoC/DI的工作職掌之一,專業術語叫Property Injection(屬性注入)。
解說前先介紹幾個測試用類別: Worker類別有個屬性Logger,接受實作ILogger介面的記錄元件;我們簡單寫個Logger類別實作ILogger,將訊息輸出到Console敷衍兩下湊數。
using System; public class Worker
{ public ILogger Logger { get; set; } public void DoSomething(string command)
{ Console.WriteLine("JOB:" + command); Logger.Log(command);
}
}
public interface ILogger
{ void Log(string msg);
}
public class Logger : ILogger
{ public void Log(string msg)
{ Console.WriteLine("LOG:" + msg); }
}
Autofac指定屬性的方法有三種。第一種的做法是透過Register()自訂物件建立細節,Register() Lambda所傳入的c即為Autofac容器(IContainer或ILifetimeScope),可透過c.ResolveType<ILogger>取得已註冊的ILogger實作。
private static void test1()
{ ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Logger>().As<ILogger>();
//方法自訂建構程序,傳回物件。建立物件時一併指定Property builder.Register(c =>
new Worker() { Logger = c.Resolve<ILogger>()
});
IContainer container = builder.Build();
var worker = container.Resolve<Worker>();
worker.DoSomething("Wash the dog"); }
第二種做法是利用Autofac物件建立事件OnActivated,於物件建立完成後指定。OnActivated事件傳入參數的Instance屬性為剛建好的物件,而Context屬性則為Autofac容器。(PS: 除了OnActivated,還有OnActivating事件可以置換Instance、注入屬性或進行其他初始化;OnRelease事件則可取代物件原有的Dispose()邏輯,提供良好的自訂彈性,細節可參考文件)
private static void test2()
{ ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Logger>().As<ILogger>();
//利用OnActivated事件,物件建立後指定Property //OnActivated事件會傳入IActivatedEventArgs, //其中的Instance為剛建好的物件、Context為IContainer或ILifetimeScope容器 builder.RegisterType<Worker>().OnActivated(
e => e.Instance.Logger = e.Context.Resolve<ILogger>());
IContainer container = builder.Build();
var worker = container.Resolve<Worker>();
worker.DoSomething("Wash the dog"); }
第三種方法我覺得最酷!
RegisterType()時直接加上PropertyAutowired(),則Autofac建立物件時將一併掃瞄物件所有屬性,只要該屬性型別已被註冊,就自動產生(或取得)Instance傳入,即便事後增加Property也無需更動註冊程序,算是貫徹了IoC/DI的精神,深得我心。
private static void test3()
{ ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Logger>().As<ILogger>();
//透過PropertyAutowired()交由Autofac自動解析 builder.RegisterType<Worker>().PropertiesAutowired();
IContainer container = builder.Build();
var worker = container.Resolve<Worker>();
worker.DoSomething("Wash the dog"); }
Comments
Be the first to post a comment