Tuesday, September 28, 2010

Invoking System.Actions with Retries using ReliableActionInvoker

 

Although some would argue that Exceptions should be thrown and handled one level up. I tend to think there are plenty of cases where by after an Exception is thrown it makes total sense to Retry the operation N number of times before finally Re-throwing the Exception up the Call stack.

One of these such cases is the simple act of Downloading a file from a Remote Server. Although the code is very simple, WebClient.DownloadFile  can and does fail frequently for a host of different reasons.

Consider the following example which simply tries to download a remote Uri to a local file path.

        private int maxRetries = 5;
        private int retriesCounter;

        public void Download(string uri, string targetFilePath)
        {
            try
            {
                var webClient = new WebClient();

                webClient.DownloadFile(uri, targetFilePath);

                retriesCounter = 0; 
            }
            catch (WebException webEx)
            {
                if (retriesCounter >= maxRetries)
                {
                    throw;
                }

                retriesCounter++;

                Download(uri, targetFilePath);
            }

        }

As you can see with a little bit of Recursion we retry the Operation a maximum of 5 times and then finally Throw the exception.

This type of code is messy to read, very repetitive and also common to errors which can lead to the dreaded StackOverflowException.

To get around this I’ve come up with what I call a ReliableActionInvoker which essentially provides a generic way to Invoke System.Actions and retry them if any Exception or an explicit Exception occurs.

Interface

   public interface IReliableActionInvoker
   {
       /// <summary>
       /// Tries to Invoke the supplied action and if any Exception is thrown will
       /// retry the number of times supplied as maxRetries
       /// </summary>
       /// <param name="action"></param>
       /// <param name="maxRetries"></param>
       void Invoke(System.Action action, int maxRetries);

       /// <summary>
       /// Tries to Invoke the supplied Action and if the Exception is of the 
       /// supplied ExceptionType will retry the number of times supplied as 
       /// maxRetries
       /// </summary>
       /// <param name="action"></param>
       /// <param name="maxRetries"></param>
       /// <param name="exceptionType"></param>
       void Invoke(System.Action action, int maxRetries, Type exceptionType);

       /// <summary>
       /// Tries to Invoke the supplied Action and if the Action throws
       /// an Exception that is contained in the supplied exceptionTypes array
       ///  will retry the number of times supplied as maxRetries
       /// </summary>
       /// <param name="action"></param>
       /// <param name="maxRetries"></param>
       /// <param name="exceptionTypes"></param>
       void Invoke(System.Action action, int maxRetries, Type[] exceptionTypes);
   }

If you’re not familiar with System.Action then I suggest you check it out on MSDN.

Implementation

    public class ReliableActionInvoker : IReliableActionInvoker
    {
        private int retriesCounter;
        public void Invoke(Action action, int maxRetries)
        {
            var exceptionTypes = new Type[0];

            Invoke(action, maxRetries, exceptionTypes);
        }

        public void Invoke(Action action, int maxRetries, Type exceptionType)
        {
            Invoke(action, maxRetries, new[] {exceptionType});
        }

        public void Invoke(Action action, int maxRetries, Type[] exceptionTypes)
        {
            try
            {
                action.Invoke();
                retriesCounter = 0; 
            }
            catch (Exception ex)
            {
                if (retriesCounter >= maxRetries)
                {
                    retriesCounter = 0; 
                    throw; 
                }
                if (exceptionTypes == null || exceptionTypes.Length == 0)
                {
                    retriesCounter++;
                    Invoke(action, maxRetries, exceptionTypes);
                    return;
                }

                if (exceptionTypes.Contains(ex.GetType()))
                {
                    retriesCounter++;
                    Invoke(action, maxRetries, exceptionTypes);
                    return;
                }

                throw;
            }
        }

  }
 

This code is pretty self explanatory. I first call Action.Invoke and catch the Exception. When no Exception Type is supplied then Retry, otherwise check if the caught Exception exists in the supplied Collection and Retry.

When the maxRetries has been reached Throw the Exception.

 

Usage

    public class WebClientDownloader : IUriDownloader
    {
        private readonly IReliableActionInvoker reliableActionInvoker;

        public WebClientDownloader(IReliableActionInvoker reliableActionInvoker)
        {
            this.reliableActionInvoker = reliableActionInvoker;
        }

        public void Download(string uri, string targetFilePath)
        {
            uri.ValidateArgumentNull();
            targetFilePath.ValidateArgumentNull(); 

            var webClient = new WebClient();

            reliableActionInvoker
                .Invoke(() => webClient.DownloadFile(uri, targetFilePath), 5, typeof(WebException));
        }

    }

Finally here’s how you could use it.

That’s all there is to it, it’s pretty simple really. I’m keen here to what you think or how you’ve approached this problem in a generic way before so feel free to comment.

The nice thing about this is it opens up the possibility to implement this using AOP but I’ll leave that to another post.

Till next time. 

Tuesday, September 21, 2010

OpenRasta vs WCF for RESTful Services

 

Not long ago I discovered OpenRasta. If you’re not familiar with it it’s described as a “resource-oriented framework for .NET enabling easy ReST-ful development of websites and services”.

After reading Rails 3 in a Nutshell I started looking at .NET a bit differently and have started being envious of the simplicity of Rails. When it comes to REST the ROR guys have definitely approached it the right way and it is baked right into the Rails framework.

When it comes to .NET there are a few different approaches you can take to create RESTful services.

  • ASP.NET MVC
  • WCF
  • OpenRasta
  • Other MVC Frameworks
  • Standard HTTP Handlers

In this post I’m going to cover how you can implement such a service using WCF and OpenRasta.

The goal is to expose a Product as JSON and XML using a RESTful uri.

product/1

WCF Approach

First let’s have a look at how to do this in WCF

Project Structure

Just create a standard WCF Service Application Project

wcfproject

DataContract

The first thing we have to do is create a DataContract which is just a Data Transfer Object that you want to be exposed by the web service.

    [DataContract]
    public class Product
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }
    }

You have to annotate the class with the DataContract attribute and properties with the DataMember attribute.

Service Contract

Now we have to define our Service Contract.

    [ServiceContract]
    public interface ICatalogService
    {
        [OperationContract]
        [WebGet(UriTemplate = "product/{id}", ResponseFormat = WebMessageFormat.Json)]
        Product GetProductById(string id);

    }

The important part here is the WebGet attribute. The UriTemplate specifies the route which you can access the Resource on and the ResponseFormat specifies the format or Content-Type to return the resource as, you can choose from Json or XML.

Having to limit to a single Content-Type is already a serious limitation and the UriTemplate being an attribute property makes it hard to change this route easily.

Also notice that the Id argument is a string, this is deliberate as the UriTemplate only supports having path segments of type string. If you try otherwise you will see an exception similar to below.

Operation 'GetProductById' in contract 'ICatalogService' has a path variable named 'id' which does not have type 'string'.  Variables for UriTemplate path segments must have type 'string'.

Service Implementation

Next we go to the Service implementation, this is pretty standard.

    [AspNetCompatibilityRequirements(RequirementsMode= AspNetCompatibilityRequirementsMode.Allowed)]
    public class CatalogService : ICatalogService
    {
       
        public Product GetProductById(int id)
        {
            var product = new Product { Name = "WCF", Id = 1 };

            return product; 
        }

     }

 

The only difference here from a standard service implementation is the use of the AspNetCompatibilityRequirements attribute on the class.

Web.Config

The only additional config required is the standardEndpoints configuration. The full config is below.

 <system.serviceModel>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint defaultOutgoingResponseFormat="Json" name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
      </webHttpEndpoint>
    </standardEndpoints>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

 

Consuming the Service

For the service to return JSON you have to specify in the Content-Type as "application/json” in the HTTP Header, for XML use application/xml.

You can consume using URI http://myrestsite.com/CatalogService.svc/product/1

Observations

Ok well that wasn’t so bad, however I’m sure you’ve already identified a few limitations.

  • Inflexible routing options, only one Uri per method
  • Only able to return XML or JSON
  • Heavy use of Attributes

 

OpenRasta Approach

OpenRasta deal with Resources, Handlers and Views, but we aren’t concerned with Views in this post.

Handlers
”Handlers are the objects responsible to act upon resources through the HTTP uniform interface and will always get called first. They're the equivalent of Controllers in other MVC frameworks.”


Resources
”Your resources are what you expose on various Uris. In OpenRasta, each thing you want to expose on the web needs to have a Resource class associated with it.”

 

Project Structure

To host OpenRasta you need to create a standard Web Application project but your Resources and Handlers can be contained in a standard Class Library project.

After installing OpenRasta you’ll need to add references to the following DLLs:

  • OpenRasta.dll
  • OpenRasta.Codecs.WebForms.dll
  • OpenRasta.Hosting.AspNet.dll

The project structure is very simple, you can split it into Handlers and Resources as shown below.

openrastaproject

Resource

The Resource or DTO is just a standard POCO.

   public class Product
   {
       public int Id { get; set; }

       public string Name { get; set; }
   }

Notice there’s no base class to inherit or any attributes. This is important as it makes it very easy to utilise Classes that you already have defined.

Handler

Handlers are equivalent to MVC Controllers or compared with WCF it’s the Service implementation.

    public class ProductHandler
    {
        public object Get(int id)
        {
            var product = new Product {Name = "OpenRasta", Id = 1};

            return product;
        }
    }

Again no base class or attributes required.

OpenRasta Config

One of the great things about OpenRasta is that the Configuration of how the Resources are accessed is completely decoupled from the implementation. The configuration has a nice fluent interface for configuring Handlers and Resources.

You can create a class with any name and implement the OpenRasta.Configuration.IConfigurationSource interface

   public class OpenRastaConfig : IConfigurationSource
   {
       #region IConfigurationSource Members

       public void Configure()
       {
           using (OpenRastaConfiguration.Manual)
           {
               ResourceSpace.Has.ResourcesOfType<Product>()
                   .AtUri("/product/{id}")
                   .HandledBy<ProductHandler>()
                   .AsJsonDataContract()
                   .And
                   .AsXmlDataContract();
           }
       }

       #endregion
   }

 

.AtUri specifies the Uri you can use to access the Resource. It’s also possible to have multiple Uris for the same resource.

                    .AtUri("/product/{id}")
                    .And
                    .AtUri("/products/{id}")

.HandledBy<ProductHandler> specifies the Handler to use.

.AsJsonDataContract() tells OpenRasta you want to expose the resource as Json

.AsXmlDataContract() tells OpenRasta you want to expose the resource as Xml

Web.Config

There is a little bit of Web.Config configuration to be done as well, this is all you need:

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpHandlers>
      <add verb="*" path="*.rastahook" type="OpenRasta.Hosting.AspNet.OpenRastaHandler, OpenRasta.Hosting.AspNet"/>
    </httpHandlers>
    <httpModules>
      <add name="OpenRastaModule" type="OpenRasta.Hosting.AspNet.OpenRastaModule, OpenRasta.Hosting.AspNet"/>
    </httpModules>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <add name="OpenRastaModule" type="OpenRasta.Hosting.AspNet.OpenRastaModule, OpenRasta.Hosting.AspNet"/>
    </modules>
    <handlers>
      <add name="OpenRastaHandler" verb="*" path="*.rastahook" type="OpenRasta.Hosting.AspNet.OpenRastaHandler, OpenRasta.Hosting.AspNet" />
    </handlers>
  </system.webServer>
</configuration>

Consuming the Service

As with WCF you need to specify the correct Content-Type to get the format you desire.

You can consume using a URI like http://myrestsite.com/product/1 or http://myrestsite.com/products/1

Observations

All in all OpenRasta is a nicer development experience and is more closely tied to the definition of REST. It is fully extensible and allows to return a Resource in any Format, including an HTML View.

 

Conclusion

I’ve only touched on a very basic use of OpenRasta, it has tons more functionality which makes developing RESTful services a breeze and also stacks up as a very good MVC framework if you’re having issues with the ASP.NET implementation. It has pretty good documentation and a strong community around it.

Check out the Comparisons table for a round up of features.

IMO doing REST in WCF just doesn’t seem very intuitive to me and is much less flexible especially when you dive deep into using HTTP Status Codes and HTTP Verbs.

If you have a requirement to develop a RESTful service instead of defaulting to WCF I urge you consider OpenRasta instead.

Till next time.

Tuesday, September 14, 2010

Defensive Programming & Argument Validation

 

The other day I found myself debugging the dreaded NullReferenceException “Object Reference not set to an instance of an object” on a piece of code written by a fairly Senior Developer.  

If you’ve been developing on .NET for more than 5 minutes then I’m sure you have come across this in your daily work and it is incredibly frustrating to try and debug.

With this post I hope to demonstrate how by using Defensive Programming you can make your API’s more robust and as a result reduce the number of bugs in your code.

If you’re a bit hazy on Defensive Programming and it’s cousins then I suggest you read the following:

Defensive Programming
Fail Fast
Design by Contract (DbC)

Validating method arguments for public methods should be a very simple concept to grasp and for most skilled developers is a  as natural as writing If statements.

The guiding principle I follow is to trust no single input and ensure that code only executes when the supplied arguments satisfy the requirements (pre-conditions). If it does not it should Fail Fast and throw an exception.

Take One

Here’s an example of what I consider to be a poorly written method.

        public OperationResult ChangeProductName(int productId, string name)
        {
            using (var uow = uowFactory.Create())
            {
                var product = productRepository.Get(productId);

                product.ChangeName(name); 

                uow.Commit(); 
            }

            return new OperationResult {WasSuccessful = true}; 
        }

Now what’s going to happen if the productId supplied is less than zero?

Well either the ProductRepository is going to throw an ArgumentOutOfRangeException or it will return a null Product and the call to Product.ChangeName is going to throw a NullReferenceException.

Either way an exception will be thrown after we have created a new Unit Of Work, which in practice could be an expensive operation.        

Take Two

So here is an example of how you could write the same method in a better way by first checking the arguments supplied satisfy the needs of the method.

        public OperationResult ChangeProductName(int productId, string name)
        {
            if (productId < 1)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException();
            }

            using (var uow = uowFactory.Create())
            {
                var product = productRepository.Get(productId);

                if (product == null)
                {
                    throw new ProductNotFoundException(); 
                }

                product.ChangeName(name);

                uow.Commit();
            }

            return new OperationResult { WasSuccessful = true }; 
        }

 

Take Three

Now the previous approach is bounds better than the first but we can reduce the lines of code by making use of some Extension Methods like so:

        public OperationResult ChangeProductName(int productId, string name)
        {
            productId.ValidateArgumentRange(1);
            name.ValidateArgumentNull(); 

            using (var uow = uowFactory.Create())
            {
                var product = productRepository.Get(productId);

                if (product == null)
                {
                    throw new ProductNotFoundException(); 
                }

                product.ChangeName(name);

                uow.Commit();
            }

            return new OperationResult { WasSuccessful = true }; 
        }

 

Extension Methods

Here are the extension methods that I use to take care of this.

   public static class ArgumentExtensions
   {
       public static void ValidateArgumentNull(this object value)
       {
           if (value == null)
           {
               throw new ArgumentNullException();
           }
       }

       public static void ValidateArgumentRange(this int value, int min)
       {
           if (value < min)
           {
               throw new ArgumentOutOfRangeException();
           }
       }

       public static void ValidateArgumentRange(this int value, int min, int max)
       {
           if (value < min || value > max)
           {
               throw new ArgumentOutOfRangeException();
           }
       }
   }

 

You maybe thinking to yourself that this is really simple stuff and I’d agree, but I felt it needed to be shared for those Devs who are still learning.

There is a new project called Code Contracts which provides a way to explicitly define pre-conditions and post-conditions, this also allows to make use of Automatic testing tools such as Pex.

IMO a few years from now Code Contracts will be as fluent to a developer as Boolean operators and we will end up with better quality API’s because of it, however right now it is only a Research project so I’m hesitant to depend too highly on it until it’s finalised and becomes part of the core .NET Framework.

There are also ways to approach this problem using Aspect-Oriented Programming but I will leave that to another post.

Till next time.

Tuesday, September 7, 2010

Load Balancing with Amazon EC2 and Elastic Load Balancing

 

Hosting your applications in the cloud yields many benefits, however it can be at times a very scary place when thing’s go wrong, and they always do.

If you love your customers then you owe it to them to make sure you have in place redundancy and ensure you provide a high level of availability.

The Amazon EC2 Infrastructure provides a really easy way to set this up using the Elastic Load Balancing feature.

Before starting you need the basic concepts of how the EC2 infrastructure works and how it can help you in your quest for high availability.

Regions


Regions in EC2 are geographical locations where the Data Centres reside and at the time of writing there are four Regions:

  • US East – North Virginia
  • US West – California
  • EU – Ireland
  • APAC – Singapore

It goes without saying that the Region you select should be always be as close to your customers as possible.

Availability Zones

Each Region has 2 or more Availability Zones. These are important to understand as they are independent from each other in that a failure of one zone does not affect the other.

Network Diagram

This is a fairly typical approach to load balancing a web application but it’s important to note that the level of redundancy is achieved by putting different instances in different Availability Zones.

LoadBalancingEC2 

The key thing to note here is that the instances you load balance should be in separate Availability Zones.

This post will be covering the Load Balancing aspect as I will leave the database redundancy to another post.

Creating The Load Balancer

Creating the Load Balancer is easy using the AWS Console

Under Networking & Security > Load Balancers you can “Create Load Balancer”.

load_balancer

This should be fairly self explanatory.

First we are assigning a name to our Load Balancer and then we are setting up the Ports the Load Balancer should listen on and forward to.

If you want to use HTTPS then you will need to do Port Forwarding as show in the highlighted image.

Configure Health Check

Next you need to setup your Health Check, this is how the Load Balancer decides if your Instance can have requests forwarded to it.

You can do this by setting the Ping Path which is an HTTP resource that is polled at an interval you define.

If it returns an HTTP result code other than 200 it will cause your instance to be deemed unhealthy and subsequently removed from the Load Balancer.

load_balancer_check

The Ping Path can be a static HTML resource, however it’s a good idea to run other any system checks and so I like to use a .ASPX file with Code-Behind instead.

Adding Instances

Here you can select Instances from all Availability Zones in your Region, as I mentioned before you should select Instances in different Availability Zones to provide a higher level of availability. Although you can have a single instance, it goes without saying you should have at least two.

load_balancer_add_instances

 

DNS

When a load balancer is created it automatically gets assigned a DNS Name. To point your website address to your load balancer all you have to do is create a CNAME record for it.

load_balancer_dns

 

Managing The Load Balancer

Now that you have setup your load balancer you can add more instances easily and get visibility of the Health of each instances by selecting the Load Balancer in the AWS Console.

Healthy

load_balancer_healthy 

Unhealthy

And this is what it looks like if you have an unhealthy instance.

load_balancer_unhealthy

 

 

Key Issues

Although EC2 alleviates lot of pain out of setting up a load balanced solution there are a few issues you need to be aware of before diving headfirst into this solution.

Connection Timeout Limit

At present the load balancer does not hold connections open for more than 60 seconds by design. So if you have any requests which take longer than a minute you are going run into problems. If you do find yourself in this position you should really be looking at how to reduce the Response times by using one-way Messaging or reducing the operation.

Static IP Address Support

Unfortunately there is currently no support for a Static IP address for your load balancer. So if you are integrating with third parties who have strict firewall policies then you may have problems. I’m hoping though that Amazon add this feature in the future as it is needed in a lot of scenarios.

SSL Support

To enable HTTPS you have to use port forwarding at the load balancer level, which can be achieved by listening on 443 and then forwarding to another port for instance 8443.

In IIS you then need to change the port in the Site Bindings, and don’t forget to open 8443 on your Firewall.

load_balancing_iss_bindings

 

Sticky Sessions

The Elastic Load Balancer does support Sticky Sessions via Cookies or QueryString however it is only works for Port 80 traffic.  
So if you’re using InProcess Session State you will need to move to the SQL based provider.

Cache 

If you’re using System.Web.Caching.Cache to cache objects then you’re also going to run into issues because of the Sticky Session problem on HTTPS. If Caching is a critical factor in your applications performance then you will need to consider a Distributed Cache solution like Memcache or Shared Cache.

 

Well that’s about all there is to it. I hope this helps someone.

Till next time.

Thursday, September 2, 2010

Implementing Custom Castle Windsor Facilities

 

If you’ve been following my posts you would know that I love Castle Windsor.

One of the many useful features I have found is the Facility and I’m going to try and give a good example how you can make use of this.

In a recent post I showed how you can add Cross-Cutting concerns to your application by using Interceptors.

Now when configuring the Container you can explicitly configure each Interceptor per Service but when you have lot’s of components it can get pretty hard to maintain after a while and can also introduce subtle issues if someone forgets to configure it correctly.

 

Below is how you would configure your Container without using a Facility. On the last line we are specifying the Interceptor explicitly.

        public void Configure()
        {
            container = new WindsorContainer();

            container.Register(
                Component.For<CacheInterceptor>(),
                Component.For<ICacheProvider>()
                    .ImplementedBy<WebCacheProvider>().LifeStyle.Singleton,
                Component.For<ICatalogQueryService>()
                    .ImplementedBy<CatalogQueryService>()
                    .LifeStyle.Transient
                    .Interceptors(new InterceptorReference(typeof (CacheInterceptor))).Anywhere);
        }

Or the XML version

<?xml version="1.0" encoding="utf-8" ?>
<castle>
  <components>
    <component id="CacheInterceptor"
             service="MyApp.Aop.CacheInterceptor, MyApp"
             type="MyApp.Aop.CacheInterceptor, MyApp"
             lifestyle="transient">
    </component>
    <component id="ICatalogQueryService"
             service="MyApp.Services.ICatalogQueryService, MyApp"
             type="MyApp.Services.Impl.CatalogQueryService, MyApp"
             lifestyle="transient">
      <interceptors>
        <interceptor>${CacheInterceptor}</interceptor>
      </interceptors>
    </component>
    <component id="ICacheProvider"
             service="MyApp.Core.Cache.ICacheProvider, MyApp"
             type="MyApp.Core.Cache.Impl.WebCacheProvider, MyApp"
             lifestyle="transient">
    </component>
  </components>
</castle>

What would be nice would be to be able to specify the Interceptor on all Components automagically and Castle allows for this with Facilities. Below is an implementation which achieves the desired result.

   public class CacheInterceptionFacility : AbstractFacility
   {
       protected override void Init()
       {
           Kernel.ComponentRegistered += Kernel_ComponentRegistered;
       }

       private void Kernel_ComponentRegistered(string key, IHandler handler)
       {
           if (typeof(IMustBeCached).IsAssignableFrom(handler.ComponentModel.Implementation))
           {
               handler.ComponentModel.Interceptors
                   .Add(new InterceptorReference(typeof(CacheInterceptor)));
           }
       }
   }

All you have to do is Inherit from the Castle.MicroKernel.Facilities.AbstractFacility and then override the Init.

You’ll see that we use the Interface IMustBeCached to identify the Component to apply the Interceptor too.

Now in your Bootstrapper all you have to do is call AddFacility on the WindsorContainer and you’re good to go.

        public void Configure()
        {
            container = new WindsorContainer();

            container.Register(
                Component.For<CacheInterceptor>(),
                Component.For<ICacheProvider>()
                    .ImplementedBy<WebCacheProvider>().LifeStyle.Singleton,
                Component.For<ICatalogQueryService>()
                    .ImplementedBy<CatalogQueryService>().LifeStyle.Transient);

            container.AddFacility("CacheInterceptionFacility", new CacheInterceptionFacility()); 

        }

Or the XML version

<?xml version="1.0" encoding="utf-8" ?>
<castle>
  <facilities>
    <facility
      id="CacheInterceptionFacility"
      type="MyApp.Aop.CacheInterceptionFacility, MyApp">
    </facility>
  </facilities>
  <components>
    <component id="CacheInterceptor"
             service="MyApp.Aop.CacheInterceptor, MyApp"
             type="MyApp.Aop.CacheInterceptor, MyApp"
             lifestyle="transient">
    </component>
    <component id="ICatalogQueryService"
             service="MyApp.Services.ICatalogQueryService, MyApp"
             type="MyApp.Services.Impl.CatalogQueryService, MyApp"
             lifestyle="transient">
    </component>
    <component id="ICacheProvider"
             service="MyApp.Core.Cache.ICacheProvider, MyApp"
             type="MyApp.Core.Cache.Impl.WebCacheProvider, MyApp"
             lifestyle="transient">
    </component>
  </components>
</castle>

 

Aside from reducing the configuration overhead another benefit of using this approach is that in your Debug or Test Environments you can easily deploy without any Interceptors and only enable them in your Staging and Production environments.