Browse by Tags

All Tags » Windsor (RSS)

Castle Windsor: Turn Off Automatic Property Injection

Suppose you have the following component: public class SomeComponent { public IEmailSender EmailSender { get; set; } } Further, you're using Windsor for IoC and have registered both this component and an IEmailSender in the container.  Whenever 'SomeComponent' is resolved, it's EmailSender will automatically be set by the container.  If you don't want this behavior, you can tell Windsor, on a per-property basis, to not auto-resolve the property with the "DoNotWire" attribute: public class SomeComponent { [DoNotWire] public IEmailSender EmailSender { get; set; } } Source: Turn off property injection/resolution Technorati Tags: .NET , Windsor , IOC , Properties

Using Windsor to inject dependencies into ASP.NET MVC ActionFilters

I'm using Windsor as my IoC container for an ASP.NET MVC application .  To get dependency injection in my controllers, I'm using a slightly modified WindsorControllerFactory from Andre Loker's post earlier this year .  It works great and allows me to easily test my controllers. I've got some custom ActionFilter s that would benefit from dependency injection.  Unfortunately, ActionFilters are attributes on controllers and methods and their instantiation is controlled by the framework.  There is no extension point to allow custom creation of the ActionFilters.  So I can't do constructor dependency injection.  However, I can do the next best thing – property dependency injection! Custom Method Invoker The ASP.NET MVC framework has an extensibility point when it comes to actually invoking actions on controllers.  The default ControllerActionInvoker does everything we need.  We need to modify it's behavior just a little bit to allow us to inject property dependencies. There's a method on ControllerActionInvoker that is used whenever an action with filters is going to be executed.  It's appropriately named "InvokeActionMethodWithFilters".  This method is passed a collection of ActionFilters that have already been created by the framework (see, this is why we can't use constructor injection).  Thanks to Simone Chiaretta for blogging about his custom Ninject-based ActionInvoker , I was able to convert his to a Windsor-based invoker with relative ease: public class WindsorActionInvoker : ControllerActionInvoker { readonly IWindsorContainer container;   public WindsorActionInvoker(IWindsorContainer container) { this .container = container; }   protected override ActionExecutedContext InvokeActionMethodWithFilters( ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary< string , object > parameters) { foreach (IActionFilter actionFilter in filters) { container.Kernel.InjectProperties(actionFilter); } return base .InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); } } As you can see, it's pretty straightforward.  All we do is loop through all of the ActionFilters and inject any dependant properties.  Those of you familiar with Windsor will realize that the IKernel doesn't have an "InjectProperties" method.  I grabbed that from Jeremy Skinner's post about using AutoFac to inject properties into ActionFilters .  He created an extension method that uses reflection to resolve property dependencies: public static class WindsorExtension { public static void InjectProperties( this IKernel kernel, object target) { var type = target.GetType(); foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (property.CanWrite && kernel.HasComponent(property.PropertyType)) { var value = kernel.Resolve(property.PropertyType); try { property.SetValue(target, value , null ); } catch (Exception ex) { var message = string .Format( "Error setting property {0} on type {1}, See inner exception for more information." , property.Name, type.FullName); throw new ComponentActivatorException(message, ex); } } } } } Now that we have the plumbing, let's hook it up! Changes to WindsorControllerFactory My current implementation of WindsorControllerFactor.GetControllerInstance looks like this: protected override IController GetControllerInstance(Type controllerType) { if ( controllerType == null ) { return base .GetControllerInstance(controllerType); } var controller = container.Resolve(controllerType) as Controller;   return controller; } I just need to add a few lines of code to add my custom WindsorActionInvoker (which is registered inside Windsor!): protected override IController GetControllerInstance(Type controllerType) { if ( controllerType == null ) { return base .GetControllerInstance(controllerType); } var controller = container.Resolve(controllerType) as Controller;   // new code if (controller != null ) { controller.ActionInvoker = container.Resolve<IActionInvoker>(); }   return controller; } Using Property Injection with ActionFilters So now lets look at how this can be used to add common data to every page.  The oft-used example of populating a list of sponsors just happened to be the exact scenario I was facing when I researched this solution.  With the WindsorActionInvoker in place, I can now create an ActionFilter to load my sponsor information into ViewData: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class LoadSponsorsAttribute : ActionFilterAttribute { public ISponsorRepository SponsorRepository { get; set; }   public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.Controller.ViewData[ "sponsors" ] = SponsorRepository...

Enabling Windsor Integration in MonoRail

I recently wanted to take on old MonoRail application and update it to use Windsor for dependency injection (DI).  The application stated as a sort of prototype and slowing grew into a decent sized application.  There's a couple of places that I want to add some unit tests and I could really benefit from DI.  So I sat down to hook Windsor into the application. There's already documentation on how to integrate Windsor into MonoRail .  After all, they kind of "grew up" together.  However, the documentation is a little old and MonoRail has gone through a number of changes (some breaking) and improvements.  The " using MonoRail " site (a sort of wiki-like site) had some information on integrating Windsor into MonoRail which was more up-to-date than the Castle docs, but still left out an important section about ViewComponents.  So I thought I'd bring everything I learned into a single blog post.  I plan to take much of this and use it to update the Castle docs as well as the "using" site. Requirements You'll need to reference a few extra assemblies in your MonoRail application: Castle.DynamicProxy2.dll Castle.MicroKernel.dll Castle.Windor.dll Castle.MonoRail.WindsorExtension.dll Custom Container The first thing is to create a sub-class of the Windsor container for your MonoRail application.  This specialized version of the container will add the following capabilities: It will add a new facility which will automatically configure our Controllers for a transient lifestyle (one instance per request).  Windsor's default lifestyle is Singleton (imagine having only a single instance for each controller – yikes!!). It will automatically register all of our controllers for us.  This is optional as you can individually register each controller, but I find the automatic registration much easier. It will automatically register all of our ViewComponents .  Like controllers, this could be done individually, but this is easier. Our custom container is really quite simple.  We'll create WebAppContainer.cs in our App_Code directory.  Our constructor will call the base class constructor that will initialize the container from the config file (web.config): using Castle.Core.Resource; using Castle.Windsor.Configuration.Interpreters; using Castle.MonoRail.WindsorExtension; using Castle.Windsor; using Castle.MicroKernel.Registration; using Castle.MonoRail.Framework; using Castle.Core;   public class WebAppContainer : WindsorContainer { public WebAppContainer() : base ( new XmlInterpreter( new ConfigResource())) { }   public void Init() { } } Now let's work on our 3 items above.  We'll plug all of this into our Init() method which we'll call later when we initialize our container. First, we add a facility for MonoRail integration.  This facility is part of MonoRail: AddFacility( "rails" , new MonoRailFacility()); Next, we register all of our controllers (yes, in one statement).  My controllers are in a separate assembly so this is how my registration looks: Register( AllTypes.Of<IController>() .FromAssemblyNamed( "YourAssemblyName.Controllers" )); If your controllers are directly in your web application, you can change "FromAssemblyNamed(…)" to "FromAssembly(Assembly.GetExecutingAssembly())". Now we also need to register our ViewComponents.  This registration will also make sure that the ViewComponents are set up with a transient lifestyle: Register( AllTypes.Of<ViewComponent>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ) .Configure(cr => cr.Named(cr.ServiceType.Name).LifeStyle.Is(LifestyleType.Transient)) ); That's it for the container!  Our complete, customized container looks like this: using Castle.Core.Resource; using Castle.Windsor.Configuration.Interpreters; using Castle.MonoRail.WindsorExtension; using Castle.Windsor; using Castle.MicroKernel.Registration; using Castle.MonoRail.Framework; using Castle.Core;   public class WebAppContainer : WindsorContainer { public WebAppContainer() : base ( new XmlInterpreter( new ConfigResource())) { }   public void Init() { AddFacility( "rails" , new MonoRailFacility());   Register( AllTypes.Of<IController>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ));   Register( AllTypes.Of<ViewComponent>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ) .Configure(cr => cr.Named(cr.ServiceType.Name).LifeStyle.Is(LifestyleType.Transient)) ); } } Integrating Our Container Now we need to hook this container into our web application.  We need to plug this into our custom HttpApplication (usually, your GlobalApplication.cs).  First, we need to add the IContainerAccessor interface: public class GlobalApplication : HttpApplication, IContainerAccessor Now add a static class variable...

ASP.NET MVC and Resolving Controllers with Windsor

Last week, while working on an ASP.NET MVC app, I wanted to plug in Windsor and use IoC to resolve my controllers.  A couple of Google searches and I came across Andre Loker's blog where he describes step-by-step how to achieve this – and it was just about a week ago!  What timing! If you read the full article, you'll see at the end he has a "More Simplifications" section which I recommend you implement.  It makes things even, uh, simpler!  Thanks Andre. Technorati Tags: ASP.NET MVC , Windsor , IoC