I am trying to wire up dependency injection with Windsor to standard asp.net web forms. I think I have achieved this using a HttpModule and a CustomAttribute (code shown below), although the solution seems a little clunky and was wondering if there is a better supported solution out of the box with Windsor?
There are several files all shown together here
// index.aspx.cs 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); } } } } // Global.asax.cs public class Global : System.Web.HttpApplication, IoCProvider { private IWindsorContainer _container; public override void Init() { base.Init(); InitializeIoC(); } private void InitializeIoC() { _container = new WindsorContainer(); _container.AddComponent<ILogger, Logger>(); } public IWindsorContainer Container { get { return _container; } } } public interface IoCProvider { IWindsorContainer Container { get; } }
ASP.NET Web Forms remains a popular framework for creating web apps. Even so, innovations in software development aren't slowing. All software developers need to stay abreast of new technologies and trends.
Castle Windsor is an inversion of control tool. There are others like it. It can give you objects with pre-built and pre-wired dependencies right in there. An entire object graph created via reflection and configuration rather than the "new" operator.
I think you're basically on the right track - If you have not already I would suggest taking a look at Rhino Igloo, an WebForms MVC framework, Here's a good blog post on this and the source is here - Ayende (the Author of Rhino Igloo) tackles the issue of using Windsor with webforms quite well in this project/library.
I would cache the reflection info if you're going to inject the entire nested set of controls, that could end up being a bit of a performance hog I suspect.
Last of all spring.net approaches this in a more configuration-oriented way, but it might be worth taking a look at their implementation - here's a good reference blog post on this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With