Two of the common threads you’ll find when using nRoute is the use of Inversion of Control (IoC) and Dependency Injection (DI) techniques – to basically map and resolve resources in your application.

Inversion of Control (IoC)

Technically speaking IoC is a very general principle that relates to inverting the flow of control, however we will take a narrower meaning to signify the decoupling of execution from the implementation. For example, consider the following interface that defines how to “execute” showing of a message:

  1: public interface IMessageService
  2: {
  3:     void ShowMessage(string message);
  4: }
Now the interface in itself doesn’t show the message, it requires an implementation – though it would be perfectly alright to use the interface to execute the implementation without directly dealing with the actual implementation. This disconnection or inversion speaks to IoC, and using nRoute we can create such disconnections by “mapping” the implementation to the resource that defines the execution:

  1: [MapResource(typeof(IMessageService))]
  2: public class MessageBoxService : IMessageService
  3: {
  4:     public void ShowMessage(string message)
  5:     {
  6:         MessageBox.Show(message);
  7:     }
  8: }
Above in line 1, we are mapping the MessageBoxService as being a resource of type IMessageService – this way, we can now look for IMessageService and nRoute will substitute it (at runtime) with the mapped implementation.

Dependency Injection (DI)

The yin-to-the-yang of mapping is resolving, in order to resolve for IMessageService we need to, one, specifically ask for the messaging service, and two, decorate our constructor with a [ResolveConstructor] attribute that tells nRoute to inject any asked for dependencies.

  1: public class CustomerView
  2: {
  3:     private IMessageService _messageService;
  5:     [ResolveConstructor]
  6:     public CustomerView(IMessageService messageService)
  7:     {
  8:         _messageService = messageService
  9:     }
 10: }

This technique is called dependency injection, and when used with IoC techniques – we get loose coupling whereby the implementation and the consumer are independent of each other (though they are both ambiently dependent on nRoute).

More Mapping and Resolving

Now there is a lot more to the workings of IoC and DI or mapping and resolving as we’ll learn ahead, but the underlying principles remains the same. However, with nRoute it is important to understand that when we put a mapping attribute onto some type, we are mapping that decorated type as the one being mapped. Further, we have many specialized versions of mapping attributes such as MapModule, which exclusively maps a module. Complimentary to MapXXX attributes we also have many DefineXXX attributes which work the same way except they do not map the decorated type, this is useful when you don’t directly own the resource you want to map, consider:

  1: [assembly: DefineService(typeof(IMessageService), typeof(MessageBoxService))]

This is exactly the same as our earlier MapResource attribute, except we are applying it at the assembly level and saying (or defining that) MessageBoxService is a service of type IMessageService. Similarly, you do not need to resolve a resource only though constructors, nRoute supports resolving dependencies via properties or fields, consider:

  1: public class CustomerView
  2: {
  3:     public CustomerView() { }
  5:     [ResolveResource] 
  6:     public IMessageService MessageService { get; set;}
  7: }

Though technically this would work the same, semantically it is quite different – when asking for a resource via a constructor, it is the equivalent of saying “I need this to work”, whereas when asked via properties (asking via fields is generally not a good idea) it the equivalent of saying “I can use this”. In other words, asking for resources via properties (semantically) signifies a degree of optionality, even though technically that might not be true.

Service Locator

One other way to get hold of a mapped resource is to use a Service Locator as the middle-man, consider:

  1: var _messageService = ResourceLocator.GetResource<IMessageService>();

Though the end result would be the same as when using Dependency Injection, here the dependency on nRoute is explicit rather than ambient. And as a general rule of thumb one should, where possible, keep the non-domain related constructs out of domain related ones – case in point being the ResourceLocator type.

Last edited Aug 29, 2010 at 5:14 PM by Orktane, version 4


No comments yet.