WebForm模型不像MVC,MVC的Controller本身使用原廠模式擷取,有ControllerFactory的概念,WebForm無法像MVC一樣直接替換Controller工廠。
構造注入就別想了,aspx直接被.NET初始化成對象的,你沒機會幹預這個過程,只能從後期的屬性注入下手。
因此主要實現思路有以下2種:
1、在aspx.cs檔案中,需要被注入的屬性直接從SpringContext中擷取對象
ClassName object = (ClassName)ContextRegistry.GetContext().GetObject("objectId");
這種方式擷取,這種比較適合於頁面數量不多,偶爾用一下下的那種(我是MVC項目裡嵌了一個aspx.cs檔案,圖個方便就用這種方式了。)
2、通過HttpModule,遍曆IHttpHandler(aspx頁面就是Page類,它同樣繼承這個介面)中的屬性,檢測Attribute並實現注入
注意一下,Castle容器比較推薦自動裝配的概念,所以Attribute上用Type來表示了,而Spring通常都是用id來描述一個對象,所以Attribute上最好帶個objectId欄位,這2種方式最好同時支援。
以下是一個Castle的容器樣本,這個同樣可以應用於Spring,實現起來差不多,Spring中容器上下文擷取方法是
ContextRegistry.GetContext();
接下來用法和Castle的就差不多了。
(這段代碼是網上抄來的,嘿嘿~ )
public partial class IndexPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Logger.Write("page loading"); } [Inject] public ILogger Logger { get; set; } } // WindsorHttpModule.cs public class WindsorHttpModule : IHttpModule { private HttpApplication _application; private IoCProvider _iocProvider; public void Init(HttpApplication context) { _application = context; _iocProvider = context as IoCProvider; if(_iocProvider == null) { throw new InvalidOperationException("Application must implement IoCProvider"); } _application.PreRequestHandlerExecute += InitiateWindsor; } private void InitiateWindsor(object sender, System.EventArgs e) { Page currentPage = _application.Context.CurrentHandler as Page; if(currentPage != null) { InjectPropertiesOn(currentPage); currentPage.InitComplete += delegate { InjectUserControls(currentPage); }; } } private void InjectUserControls(Control parent) { if(parent.Controls != null) { foreach (Control control in parent.Controls) { if(control is UserControl) { InjectPropertiesOn(control); } InjectUserControls(control); } } } private void InjectPropertiesOn(object currentPage) { PropertyInfo[] properties = currentPage.GetType().GetProperties(); foreach(PropertyInfo property in properties) { object[] attributes = property.GetCustomAttributes(typeof (InjectAttribute), false); if(attributes != null && attributes.Length > 0) { object valueToInject = _iocProvider.Container.Resolve(property.PropertyType); property.SetValue(currentPage, valueToInject, null); } } } }