I'm really excited to introduce the latest version of nRoute - this has been brewing with me for a long-time and I'm really happy about the feature-matrix that this release brings to bear. This release is a major one, for a couple of reasons - first, this release propels nRoute to three platforms, two, it takes big strides in making the underlying infrastructure asynchronous, three, it significantly updates the navigation infrastructure, and four, it brings extensible Dependency Injection (DI) into play which allows top-down composition to cascade through the application.

nRoute Overview

ApplicationFeatures

Now my intention with this post is to cover what's new and what's changed, but before that I want to just give an overview of nRoute. Basically, nRoute is a composite application framework that allows you to break and compose your application using various application-level constructs, as show in the diagram above. It is highly prescriptive in terms of its use of Navigation, IoC, DI, and other MVVM design patterns. It comes in two flavors, the full framework (nRoute.Framework.dll), and the toolkit version (nRoute.Toolkit.dll) which lacks the Routing Engine and the sub-features associated with it (shown in green above).

The Routing-Engine basically provides Url addressable content and actions - this helps you break your applications into smaller-chunks that can be brought together in a very loosely-coupled fashion - just like on the Web. The Messaging-Framework allows for loosely-coupled communication between one or more parties, without either having direct knowledge or keeping direct references between each other. Lastly, the Resource Locator Framework (RLF), which is an IoC component (and now a DI component too) allows for extensible and open-ended composition at runtime - build upon it are various features such as Modules, Services, View-Services, View-ViewModel support etc.

For more information on all of the above, check out some of my older posts, though do note that quite a bit has changed since:
Introducing nRoute: an application-flow framework for Silverlight and WPF
Introducing nRoute.Toolkit for Silverlight (Part I)
Introducing nRoute.Toolkit for Silverlight (Part II)

I'm looking into put together a single document that highlights nRoute's depth and breath, but for now these blogs posts will have to serve as scattered documentation.

Multi-Platform Support

SimpleMVVMWith this release we now have out-of-the-box support for Silverlight, Windows Phone 7 and WPF. This is a big branch-out from nRoute's Silverlight-only roots, but between the growing convergence of WPF and Silverlight and three independent WPF implementations of nRoute out in the wild, we've managed to bridge the gap. All the same, it is important to note that for the foreseeable future the center of gravity of nRoute, in terms of features and scope, will remain aligned with Silverlight despite the wider canvas afforded by WPF.

Asynchronous Routing and Navigation

First a little background, in nRoute we have two core interfaces that handle routing and navigation - the IRouteHandler interface essentially "sources" the response for an Url request (i.e. gets the content), and INavigationHandler handles the routing response (i.e. displays the content). These are like the two main cogs that make content sourcing and its visualization work, and with this release we tweaked both of them to make them work asynchronously. With respect to IRouteHandler, rather than just returning a response, we changed it to return an IObservable of the response - a seemingly small change, but it makes a fundamental difference:

IRouteHandler

Secondly, as it was, INavigationHandler separately processed the request and the response - which allowed us to be asynchronous in-between the two calls. But now with this release we've also tweaked INavigationHandler to respond to any navigation request asynchronously, by returning a yah/nah through a callback. It is also a little change, but has a profound effect:

INavigationHandler
With the new definition, we can now respond by consulting with the active View/ViewModel as to if we can proceed - and this is important as most of the can/should navigate reasons are contextual to the task at hand. In terms of the normal designer-developer workflow you don't need to deal-with the INavigationHandler or IRouteHandler directly - rather, as we'll see next, you deal with some predefined interfaces/contracts that optionally provide you control over how things like closing the current-view, navigating to a new view etc work. One common scenario where this really helps is when you want to navigate-away from a page, but before that you want to contextually consult the user about cancelling, saving changes, or continuing with the navigation - this gives your the entry point for that.

Formalizing Container-View/ViewModel Communication

One of the common problems with MVVM tuned applications is how do we communicate with the ViewModels from the outside/shell - well, the answer is simply, define a contract and use that as the basis for communicating. And with the new release we've put in place some mechanisms to make this extremely easy and extensible - I'll need to defer showcasing this to another post, as I want to explain it with an example. Making use of this technique, we've got three build in contracts that are used by various navigation controls to communicate with your View/ViewModel (which ever implements it). These contracts are refinements over what was available before, but they are much more well-strung now:

ISupport_thumb[2]ISupportNavigationState allows you to optionally participate in a container-maintained state management functionality (just as before, but the interface has changed). ISupportNavigationLifecycle (also changed, but like before) helps with lifecycle integration, by passing-in the parsed Url-based tokens along with the request's parameters, and as mentioned above it also allows you to participate in the closing of the active-view. A very simple way to exercise both the ISupportNavigationState and ISupportNavigationLifecycle interfaces is to use the new NavigationViewModel, which in addition to the two interfaces also implements INotifyPropertyChanged interface. Lastly, the ISupportNavigationFailure is used to visualize navigation error information, as we'll see ahead.

Globally Named Navigation Containers

Often you'll find that you want to trigger navigation in some container that is not directly accessible within the operating name-scope or even via the VisualTree - for such cases, we've introduced a simple mechanism to globally register a container with a string-based identifier, and then target the container for navigation using the same string identifier.

NavigationHandlerBehaviour 
To register any container globally use the NavigationHandlerBehavior and simply provide a name - as shown in the figure above. Now, internally we keep a weak-reference, and if another container registers with the same name then the last-one-in wins. Secondly, to target the globally-registered container specify the HandlerName (as shown above) on the any of the various navigation inducing behaviors (described ahead).

Application-Wide Default Container

In earlier versions to specify an application-wide default container, we had to hijack the Application class - well, no more - we specify the application's default container by just using the above mentioned NavigationHandlerBehavior and checking the IsDefaultHandler option. Also, in case of multiple opt-ins the last-one in wins, and to access the default container programmatically use the NavigationService static class. Note, when you want to use the application-wide default container you don't need to specify the navigation handler name.

Browser-Shell Integration

Browser-shell integration was earlier quite messy, now all you need to do is to drop the NavigationShellIntegrationBehaviour and you are done - clean and simple, and there are no options to fiddle around too.

NavigationShellBehaviour
This behavior makes use of the Silverlight's built-in Browser-History Manager, however it has the limitation of only being forward-only, which means you can't use it with navigation containers that allow directional navigation (like BrowsingNavigationContainer). For use with direction-aware containers I'll release an out-of-bound behavior, which will use of a different Browser-History Manager. Also, note this behavior is not available for WP7 or WPF, and when in Out Of Browser (OOB) mode it disarms itself.

Added StatefulBrowsingNavigationContainer

Unlike WPF/SL we have a flexible approach to containers (aka Frames) that display navigation results; in nRoute our approach is to offer different containers for different navigation use semantics - so some offer browser like state-management, some offer browsing history, while others just offer onwards-only navigation. Now, with this release we're adding a new navigation-container called "StatefulBrowsingNavigationContainer", it allows browser like back-forward navigation whilst allowing each page-type to share the same common state. Think about how in a Web-Browser each individual page in your navigation history keeps its own navigation state - well, with this container each page-type will have one common state whether they be in the forward or back stack or even if you just directly navigate to the page. So when you back up or go forward, the same single state will be returned - and I personally find this quite useful for desktop class application. This is actually an hybrid of StatefulNavigationContainer and BrowsingNavigationContainer.

Also as a related point, with this release we've update all the build-in container templates, they now match the Silverlight's standard way of templating content controls. Another changes is that the template now shows an overlay with an animated indicator whilst navigating (it uses a spinning indicator by Felix Corke).

Navigation Adapters

NavigationHandlers  
Implementing navigation containers in nRoute is really quite simple, all you really need is an INavigationHandler implementation - and there are two approaches to this, one is to make custom controls from the ground up, which we have (as shown in the hierarchy above) and the other approach is to tack this interface onto existing controls, which is relative easy. However, inheriting and extending controls is not exactly pleasant, and indeed in some cases it's not even viable - so as an alternative, with this release we've standardized a way to create so-called "navigation-adapters". These are essentially behaviors that implement INavigationHandler and can be drag-dropped onto any targeted control. And by the virtue of having the behavior all of nRoute's navigation infrastructure will seamlessly work around your targeted control. So for example, you want to handle navigation in a Tabs-Control, write a little behavior for it, drag-drop it, and you're done - no need for extending any control.

Now, because a lot of the functionality for adapters is common we've build in an adapter base class, obviously called NavigationAdapterBehaviorBase<T>. It only requires you to handle the displaying of content when navigated upon - and it's basically like visualizing the navigational content. Consider you could make a custom navigation adapter for a 3D panel, and each navigation adds to the 3D content. Additionally, we've also create an ItemsControl navigation adapter (numbingly called ItemsControlNavigationAdapterBehavior) that basically can append to an ItemsControl any navigated upon content. And because it's an ItemsControl, you can use this will all sorts of panels. This is a very powerful and flexible model and I'll have to showcase it separately, but the idea behind it was to allow you to create custom use-models, not just the linear navigation apps we are all used to. You can even create MDI type of application, and combine it with all benefits of a navigation-style app.

Abstracting Container Behaviors

One other new thing we've done is to abstract the common navigation-related functions such as refreshing, navigating back/forward, purging journals etc into well-understood interfaces; some of these are:

ISupportContainerThis helps, because now we can consistently target functionally-similar containers, and indeed we've build into nRoute the following behavior-actions to that take advantage of the abstracted commonalities:

NavigationBehaviours

NavigateActionSo like if you want to refresh a container, drag-drop the RefreshNavigationAction, point to the handler and you're done. Now, the most useful of these behaviors has to be the NavigateAction - which as it self-suggests induces navigation, and its use is shown in screenshot to the right. The Handler property is useful when you want to directly bind to an INavigationHandler object, but mostly you'll either just specify the HandlerName or actually not specify any handler (as we'll see ahead, why). Note, the Handler Name can either be an element name within the control name-scope, or it can be a globally-registered handler name (as we described earlier). The parameters collection allows you to pass-in a name-value collection with any navigation request, think of it as a Form/Request Collection in Web-Forms. We'll get to the SiteArea in a bit, and the Url is obviously the Url one wants to navigate too.

Now, I just wanted to point out the workflow of how we resolve the navigation-handler (this is slightly changed from before), we have a five-step approach, described below:

  1. If we have a navigation-handler directly specified/bound (Handler Property), then we use that
  2. If we have a handler-name specified, we check for an element with that name in our control name-scope; if found we use that
  3. If we have a handler-name specified, we check against the list of globally-registered handlers; if found we use that else throw an exception stating that the handler name was not found
  4. We look up in the visual-tree for an INavigationHandler, it can either be an control implementation or it can be via an attached adapter - we check for either; and if found we use that
  5. Lastly, we check if we have an application-wide container specified, if so, we use that - if not then, we return null and the handling logic would normally throw an exception stating handler not found

The interesting part is part 4, which basically says look upwards in the Visual-Tree and if you find any INavigationHandler use that - this basically allows you to default to the most immediate handler, just like in web-pages/IFrames, and it gives you the browser like use-semantic. And note, you can easily have containers-within-containers or use containers side-by-side, like in a master-detail scenarios.

Support for Error Pages

ErrorPage
One of the expectations with navigation-style apps is that when you can't get to any resource, you get a nice little exception page - well, in earlier releases that was not the out-of-the box behavior with nRoute. But with this release, we've not only added a default error page (shown above), but also allowed you to put in your custom page. Custom error pages are easy to create, all you need to do is to implement the aforementioned ISupportNavigationFailure interface - and you can set them by setting the ErrorUrl property on all built-in containers.

Also, the default error page can be reached via the Url "About:Error", and the WP7 counterpart looks a bit different as it's specifically tailored for the mobile experience - it even makes use of the active phone theme. And in cases where you don't want to show error pages at all, you can override the ShowFailedNavigationState method to handle a navigation failure in whichever manner suitable to your needs.

Introducing Controllers

One of the concepts in earlier version of nRoute was Url-addressable "Actions" - but now its got the axe, as it required that each action have a corresponding class, plus it wasn't represented in a strongly-typed manner. A replacement is in hand, have a look:

   1: [MapController("Shell/Tasks/{Action}"]
   2: public class ShellController : Controller
   3: {
   4:     public ActionResult Settings()
   5:     {
   6:         return new NavigateResult("Pages/Shell/Settings/");
   7:     }
   8:  
   9:     public void Exit()
  10:     {
  11:         Application.Current.Shutdown();
  12:     }
  13: }

If the above looks familiar, well then say hello to MVC in Silverlight - basically, we've got the full MVC style controller-action thing in nRoute. The idea is to have Url-executable actions, and Controllers provide us the necessary encapsulation required for something that is rooted in the UI. Additionally, we have the full range of extensibility points available in MVC, for example custom ActionResults, custom ActionNames, even custom ActionInvokers if you so require. And because this is build-upon the desktop-class routing engine you can even get the full MVC routing semantics, including setting custom route handlers with default values etc; or to keep your sanity just use the MapController attribute as shown above. Further, you can pass in action parameters to methods either through Url-tokens or using the parameters collection associated with the controller-action request.

Controller Behaviors

ControllerBehaviours
To execute Controller based actions we basically have the ExecuteControllerAction behavior, which can be attached to any sort of trigger. The use-semantics of executing an Controller is exactly the same as the NavigationAction (which was described earlier), and indeed they inherit from the same base-class. And the reason controller-actions optionally associate with navigation handlers, is because in some cases, they allow you to execute an action against an navigation handler.

Introducing SiteMaps

   1: <nRoute:Application.ApplicationLifetimeObjects>
   2:         <nRoute:nRouteApplicationService>
   3:             <nRoute:nRouteApplicationService.SiteMapProvider>
   4:                 <sm:XamlSiteMapProvider>
   5:  
   6:                     <sm:SiteMap>
   7:  
   8:                         <!-- AREAS -->
   9:                         <sm:SiteMap.Areas>
  10:                             <sm:SiteArea Key="ModuleA"
  11:                                  RemoteUrl="nRoute.ModuleA.xap"
  12:                                  InitializeOnLoad="false"/>
  13:                             <sm:SiteArea Key="ModuleB"
  14:                                  RemoteUrl="nRoute.ModuleB.dll">
  15:                                 <sm:SiteAreaInfo Key="ModuleA" />
  16:                             </sm:SiteArea>
  17:                         </sm:SiteMap.Areas>
  18:  
  19:                         <!- ROOT NODE -->
  20:                         <sm:SiteMap.RootNode>
  21:                             <sm:NavigationNode Title="Home Page"
  22:                                 Url="Pages/Content/HomePage/"
  23:                                 SiteArea="ModuleB">
  24:                                 <sm:NavigationNode Title="About Us"
  25:                                     Url="Pages/Content/AboutUs/" />
  26:                                 <sm:NavigationNode Title="Contact Us"
  27:                                     Url="Pages/Content/ContactUs/" />
  28:                                 <sm:ControllerActionNode Title="Exit"
  29:                                     Url="Shell/Tasks/Exit/" />
  30:                             </sm:NavigationNode>
  31:                         </sm:SiteMap.RootNode>
  32:  
  33:                     </sm:SiteMap>
  34:  
  35:                 </sm:XamlSiteMapProvider>
  36:             </nRoute:nRouteApplicationService.SiteMapProvider>
  37:         </nRoute:nRouteApplicationService>
  38:     </nRoute:Application.ApplicationLifetimeObjects>

Well, here's another nod to concepts from web-world, we've basically borrowed the concept of SiteMaps right from ASP.NET and indeed you get the same type of semantics of specifying hierarchical set of nodes. However, unlike ASP.NET, we have two specific built-in node types that directly relate to navigation and controller-actions (see NavigationNode and ControllerActionNode above). Also, this is an extensible architecture, so for example you can have ICommand based nodes or indeed custom ones based on your application executable-functionality.

SiteMapNodes

Above is a screenshot from a sample application (you can actually download it from Codeplex) that shows how you can use the SiteMap definition to integrate within your application. Alternatively, you could have menus or toolbars based on your SiteMap definition. Plus, to make life that much easier, build into nRoute are a couple of behaviors (see the diagram below) that allow you to execute any SiteMap Node. Also you can give each SiteMap Node a unique key, and use that to Navigate (see NavigateNodeAction) or execute the associated Controller-Action (see ExecuteControllerNodeAction) - this way you can abstract the Urls out.SiteMapBehaviours

SiteMaps are sourced using a "SiteMapProvider", which is basically tasked to yield a SiteMap. You specify the application's lone SiteMapProvider in nRoute's ApplicationService declaration (which is defined in App.xaml) - and so, when the app starts, nRoute tries to load the SiteMap using the specified provider. Built-into nRoute are two providers, one, a XamlSiteMapProvider which, as shown in the xaml above, allows you define the SiteMap in xaml itself. The other included provider is the XmlSiteMapProvider, it allows you to load the SiteMap definition from an external xml file. And to ensure maximum flexibility, the SiteMap infrastructure is designed to load asynchronous, so it can tolerate loading of SiteMaps dynamically/lazily. Furthermore, you can create your own custom SiteMap providers, like one perhaps using a database to dynamically assemble your application's parts at runtime.

Introducing SiteAreas

SiteAreaBehaviour Again I've borrowed the Areas terminology from  MVC, but in this case you can think of them as external resources (like xap/dll files), each SiteArea is uniquely identifiable using a key. The idea is to define all external resources in one well-understood place, so that both your code and the entire nRoute infrastructure can avail them at runtime. So for example, if you want to navigate to "Pages/Content/ContactUs" and it is in "ModuleB.dll", then by defining it as a Site Area and indicating the same in your navigation request (see right) the infrastructure will automagically load it when asked to navigate, and then navigate to your destination once the SiteArea is loaded. This way we get both easy-to-use semantics and very loosely-coupled bridges over external resources.

Now, in terms of the technical workings, when a SiteMap based external resource is requested, the navigation-engine will first check if the SiteArea (in our case) named "ModuleB" is loaded or not, if not it will download it, initialize any resources within it, and then continue with the navigation. All this takes place seamlessly, in fact if ModuleB had any dependencies (like "ModuleA" in the case above) they will be topographically resolved to the nth level. Also, the SiteMap infrastructure can also check for circular dependencies, just like Visual Studio does references.

Honestly, I don't think I could have made this any simpler, it is tightly integrated with the asynchronous nature of the routing engine and therefore works with anything build upon it, obviously like built-in navigation and controller facilities. However for other or custom uses you also have programmatic control over loading both SiteAreas and the SiteMap; and you can also specifically indicate which SiteAreas to load when the SiteMap initializes. Keep in mind, use of both SiteMaps and SiteAreas is totally optional, however, use of SiteAreas is not at all possible with WP7 because you can't load external resources by design. Lastly, note that SiteArea internally makes of RemoteResourceLoader component, which with this release has been totally revamped, and now makes use of IObservables to asynchronously load and map external resources.

Introducing Dependency Injection (DI)

nRoute already has an MEF like IoC component that is both extensible and open-ended, now, with this release it meets its significant other - an extensible DI system. The new DI systems' use can be summed-up by two attributes ResolveResource[Attribute] and ResolveConstructor[Attribute]. You put ResolveResource attributes on properties, fields and parameters; it optionally allows you to specify which named resource to use, and it also allows you to indicate as to if some resource is "nullable" in which case if not found it won't throw an exception. Further, in Silverlight you can only use it with public fields/properties, as use with non-public members is not allowed. And you use the ResolveConstructor attribute to indicate which constructor to use at runtime - its use is required unless you have a default public constructor, and in Silverlight you are obviously limited to a public constructor.

Now, like the resource "mapping" infrastructure in nRoute, the dependency "resolving" infrastructure is also totally customizable - if you want to provide your own custom resolving methodology, then inherit from the ResolveResourceBase attribute and provide your own custom implementation. Included in nRoute are two such custom resolving attributes, ResolveChannel attribute and ResolveViewModel attribute. The ResolveChannel resolves an Observable Channel, and the benefit of using it is that it bypasses the resource mapping layer and goes directly to the Channels infrastructure - plus, it allows you to specify additional contextual options. Similarly, the ResolveViewModel attribute can resolve an instance of the ViewModel for a View; note below how we appended that to the parameter of the constructor:

   1: public partial class PageA : UserControl
   2: {
   3:     [ResolveConstructor]
   4:     public PageA([ResolveViewModel(typeof(PageA)]Object viewModel)
   5:     {
   6:         InitializeComponent();         
   7:         this.DataContext = viewModel;
   8:     }
   9: }

This kind of extensibility moves beyond the traditional A is to B type of DI, as it is semantically-rich and can mesh your domain-logic seamless with the DI process - all the while keeping infrastructure concerns separate from the content. Further, note all resources created by the nRoute infrastructure like Services, Views, ViewModels, Modules etc can make use this DI system - so when defining your ViewModel you can ask it resolve services you require:

   1: [MapViewModel(typeof(PageA))]
   2: public class PageAViewModel : ViewModelBase
   3: {
   4:     private readonly IRepositoryService<Customer> repository;
   5:     private readonly Lazy<IMessageViewService> _messageViewService;
   6:  
   7:     [ResolveConstructor]
   8:     public PageAViewModel(IRepositoryService<Customer> repository, 
   9:         Lazy<IMessageViewService> messageViewService)
  10:     {
  11:         _repository = repository;
  12:         _messageViewService = messageViewService;
  13:     }
  14:     ...
  15: }

Locator Adapters for Higher-Order Dependencies

Another point of extensibility are so-called Locator Adapters, this is inspired by Common Context Adapters concepts which is all about abstracting out the IoC container specifics by using higher-order dependencies. For example, consider if you want to lazy-load a resource, normally you'll defer it's use till required, once require you check if it's null, if so then ask the IoC to load it etc - now this both quite messy and leaky, so instead why not have the DI resolve a Lazy<T> which would internally abstract away all the container and loading specifics - and you're level of involvement is limited to asking for Lazy<T> rather than a type T. Based on this simple but powerful concept, nRoute's DI can resolve the following higher-order dependencies, for any resource of type T.

  • T[]
  • Func<T>
  • Lazy<T>
  • Lazy<T, Metadata>
  • Future<T>
  • List<T>
  • ICollection<T>
  • IQueryable<T>
  • IEnumerable<T>
  • IEnumerable<Func<T>>
  • IEnumerable<Lazy<T>>
  • IEnumerable<Lazy<T, TMetadata>>
  • IChannel<T>

And if that's not enough, you can create your own custom adapters and register them with nRoute's Resource Locator Framework (RLF). Again, like the MapChannel attribute we saw earlier, you can extend the DI to your custom domain specifics, just as we do with IChannel<T> above. Another interesting adapter is the Future<T>, which when used says that we might not have this resource-type available as of now, but in some point in the future it might be - so just resolve a Future<T> resource and we will check against it if the resource is available or not (via its IsValueAvaliable property) prior to using it - using this you've abstracted away the IoC/DI system specifics.

Another problem with DI in an open-ended IoC framework like MEF and RLF is we have no idea what is a resource and what is not; MEF deals with this by rejecting the composition, nRoute deals with this by throwing an exception - simply because without a resource-type registration we don't know if type XYZ is a bonafied resource or not, and we simply can't accept anything is a resource policy, as that's an endless loop. Now to solve this conundrum, keeping in mind the open-ended nature of nRoute, we have a special MapAsKnownResource attribute (with a parallel DefineAsKnownResource attribute) which tells the RLF that this type is a known resource type, and so accept any request for it. This way we can reject any erroneous-requests, but still accept the unknowns.

   1: [MapAsKnownResource]
   2: public interface IExecuteService
   3: {
   4:     void Execute();
   5: }

So for example, with the code above even if we don't have any registered implementations of IExecuteService, we still accept it as a bonafied resource type because it is specifically earmarked as such. Note, normally you don't need to put this on every resource because you'll have an implementation available at the same time - in case you don't, use this.

Dependency Recomposition Support

Dependency recomposition is a fantastic facility, however it is something that can without due-consideration lead to all sorts of memory leaks, because in most likelihood you are tying a variable to a static "source-of-resources", whose lifetime will mostly likely exceed that of your variable. So for recomposition with RLF, I've made available three specific adapters that "by default" will not lead to memory leaks as it makes use of "smart handlers" infrastructure in nRoute. The three supported adapters for a resource of type T, are:

  • ReadOnlyObservableCollection<T>
  • ReadOnlyObservableCollection<Lazy<T>>
  • ReadOnlyObservableCollection<Lazy<T, Metadata>>

Now this is not a be-all list, as  you can extend it with your custom adapters as you require - but I think for most common uses these should suffice. Its usage is similar to any resource, and doesn't require any additional opt-ins:

   1: public class ServicesViewModel : ViewModelBase
   2: {
   3:     [ResolveResource]
   4:     public ReadOnlyObservableCollection<IExecuteService> Services { get; set; }
   5: }

As you would know, ReadOnlyObservableCollection implements INotifyCollectionChanged, which therefore can be used to notify when recomposition happens and to stop the recomposition one just needs just nullify the variable/property (note, nullify all instances of it, and also remember to remove any event-handlers attached to the collection to stop recomposition).

Observable Channels

We've made sweeping changes to the Observable Channels in nRoute -  for the better - the performance is up 4 fold, we've aligned it much more with the Observable pattern, and now we also have compatibility with Rx-framework.

IChannel
Each channel is now defined as an IChannel<T> (as can be seen above) and in Rx-speak an IChannel is a Subject which means it both an observer and observable. And being both an observer and observable means that through an IChannel you can both publish and subscribe - which is the same as before, but now you can direct do using the IObservable<T> and IObserver<T> interfaces. A new thing with this release is that you can also publish exceptions (using OnError) and this is appropriate because, as I explained before, a call to any operation in .NET has two possible outcomes an explicit result or an implicit exception, and the same two possibilities are reflected here. One important thing to note is that you CANNOT call OnCompleted on an IChannel because an observable channel is usable through-out an application's lifetime, doing so will only raise an exception.

A new thing with this release is that we have the concept of a public and private channels - each type of channel has one default public IChannel<T> associated with it, and additionally you can any number of private channels each identifiable with an unique string-based key (non-case specific). The API is very simple, below we are subscribing and publishing on a public channel and a private channel (identified with the key "Test"), have a look:

   1: // Subscribe
   2: Channel<string>.Public.Subscribe((m) => MessageBox.Show(m));
   3: Channel<string>.Private["Test"].Subscribe((m) => MessageBox.Show(m));
   4:  
   5: // Publish
   6: Channel<string>.Public.OnNext("Hello Public World!");
   7: Channel<string>.Private["Test"].OnNext("Hello Private World!");

Now above the "Subscribe" is an extension method, and you have couple of them with lots more options. Further, the OnNext method (and OnError method too) has an overload that takes in a Boolean suggesting as to if you want to publish it asynchronously. If this is not not enough you can always call in the cavalry, in form of Rx-framework, so for example:

   1: Channel<string>.Public.
   2:     Delay(TimeSpan.FromSeconds(10)).
   3:     TimeInterval(TimeSpan.FromSeconds(5)).
   4:     Select((t, m) => m.Substring(10)).
   5:     ObserveOn(DispatcherSynchronizationContext.Current).
   6:     Subscribe((m) => MessageBox.Show(m));

So above, we are delaying the listening by ten seconds, and at every five second interval we are selecting a substring of the first ten characters, and observing it on the dispatcher thread, to show the resulting string via a message-box - nonsense use, but the point is you get the full power of the Rx-framework for use with your channels. Though note Rx-framework is not required by default, but you have the option to exercise it if required (aka nRoute doesn't have a dependency on Rx, but we have binary compatibility).

Old Channel Ways Survive

Despite the new API I've show above, you can still use the old-style API to publish/subscribe against observable channels (like before) - and it has full parity to the new API. And as an extended use-case it even allows non-generic usage of channels, which can be really handy sometimes.

ChannelObserver
The Channel static class follows the "publish/subscribe" metaphor, and its usage is also quite simple:

   1: // Publishing through the Channel class
   2: Channel.Publish<string>("Hello Public World!");
   3: Channel.Publish<string>("Test", "Hello Private World!");

Now one of the big internal change to channels is that now by default all subscriptions are NOT weakly referenced - they are strongly referenced and must be manually disposed/unsubscribed. This change was required for both Rx-framework and use of lambda statements, as by their nature lambda's can't survive a weak-reference subscription (technically, they can by lifting some reference into their scope, but that's leaky design) - which meant that they would have unsubscribed as soon as you exited the method they were declared in. However, if you know what you are doing, you can still make lambdas weakly-referenced, using an overloaded subscription method. Despite this change, the ChannelObserver<T> by default still by maintains a weakly-referenced subscription, which is exactly like before - and in fact, I still highly recommend the use of ChannelObserver<T> in your Views/ViewModels as you normally wouldn't want to deal potential memory leaks if you did not unsubscribe. Remember channels (private or public) are static resources, and their lifetime spans that of the application - so when you hitch something to it, you are also potentially extending the attaches' lifetime to match that of the channels (Hello, Memory Leak).

ICommand Infrastructure Updates

Earlier we had this distinction between so-called ActionableCommands and ActionCommands, well no more - we've unified the two, and now we just have ActionCommand and ActionCommand<T>(.) Also, I've done bit a of clean-up under the hood, particularly I've abstracted the ICommand base-classes which can now be used to make stand-alone commands (I'll show a nice use-case in a separate post).

TriggerParameter Now, one of the common questions I get asked is how do we pass-in event-arguments to the ViewModel, well the simple answer is that you don't. An event-argument is a View-specific construct, it has no place in the ViewModel, obviously because separation of concerns is the entire point of View-ViewModel partition. That being said, in case where "data" from the event-argument has to passed-onto the ViewModel, we now support that via the new TriggerParameterConverter property (see right) on the ExecuteCommandAction behavior.

TriggerParameterConverter accepts an IValueConverter, which converters the Trigger's parameter for use as the Command's parameter. I hope that is not confusing, what happens is each trigger gets to pass onto its to-be-triggered action(s) a parameter, and in the case with EventTrigger (used above) it passes in the event argument from the selected event (in this case selected above that would be the SelectionChangedEventArgs type). And by specifying the converter for converting SelectionChangedEventArgs to something the ViewModel can understand and digest, we are able to bridge the View-ViewModel separation without violating the separation agreement. Moreover, this works with all sorts of triggers, and remember each trigger passes-through whatever is appropriate to its operation, so in this way we have a very flexible approach that works across the board and not just with events.

New Behaviors and Triggers

UpdateBindingExplicitly I've added three sets of new behaviors, the first of which is called UpdateBindingExplicitlyAction - it as the name suggests allows you to update a property binding explicitly. Consider the example in the screenshot to the right, it shows a TextBox to which we've attached our UpdateBindingExplicitly action. Now, what we're saying there is that whenever the TextChanged event occurs, update the binding for the property called "Text". It's as simple as that - note you can pair the update action with any sort of of trigger, and it will update any (non-read only) dependency property's binding.

The second new action is SetFocusAction (and an accompanying TargetedSetFocusAction); this action allows you to set the focus on any element by pairing it with a Trigger. In fact this is often a common newbie question, how do you set focus in a MVVM application? Well, here is one simple and designer-friendly answer.

The other two new behaviors are BoolValueDisableBehavior and NullValueDisableBehavior, they both allow you to disable or pseudo disable an element depending on a Boolean value or a Null value. This actually tackles an acute problem in Silverlight, where most of the controls don't support an IsEnabled property, and so you can use this behavior to gloss over the differences by disabling input and reducing the opacity in cases where the control is not inherently disable-able. For example, below is a Border control (in Silverlight it doesn't have an IsEnabled property), that is automatically "disabled" when there is no loaded worksheet in the backing ViewModel.

PseudoDisabled

The xaml for this looks like:

   1: <Border ... >
   2:     <i:Interaction.Behaviors>
   3:         <nBehaviors:NullValueDisableBehavior Value="{Binding Worksheet, Mode=OneWay}"/>
   4:     </i:Interaction.Behaviors>
   5: </Border>

Woo, Finally

For a 128kb/75kb (Full Framework / Toolkit Version) additive to your xap files, I think nRoute packs a punch - and with the new release it is more wholesome than ever. Definitely, we still have a long way to go, but I think the big difficult steps have been made. And the focus here forth will not be so much on features but better execution and quality, and for the immediately proceeding release Designer/Blend support will be the big go-go. And finally, finally, a lot of the new features in this release have come from user's suggestions and pain-points (thanks guys), and so I encourage anyone and everyone with feedback to chime in - there is a receiver on the other end.

You can download nRoute (all three versions) from Codeplex including the source
- Targets Silverlight 3 for Web  (Silverlight 4 version will be out once RTM tools are posted)
- Targets Silverlight 3 for Windows Phone 7
- Targets .NET 3.5 for Desktop (.NET 4 version will out with Silverlight 4 release)

Note, we have 6 dlls, 3 for nRoute.Framework and 3 for nRoute.Toolkit

nRoute Dependencies
- System.Windows.Interactivity.dll from Blend SDK
- System.Observable.dll from Rx-framework
 
View the Officer Xcel Demo App, source is also available on Codeplex
more samples to follow

PS: I want to specially thank Carlos Álvarez, he really helped me with throughout the way, especially with the WPF version - it wouldn't have been possible without his support. You must check out his WPF Chronos Framework, its designed for developing (super) MDI applications using Windows Presentation Foundation.

Posted by Rishi on 13-Apr-10 1:36 PM, 22 Comments

Categories: WPF, WP7, Silverlight, nRoute
WP7Shot1

WP7Shot2

Well, that was painless - nRoute, a forthcoming version, is now running on WP7S and with surprisingly very little omitted. The only thing that got the full-chop was a remote resource (dll/xap) loading helper class other than that just some nip-tucks and if-elses did it.

I'll be releasing toolkit version for the Silverlight, Desktop (.NET 3.5) and WP7 next week, and I'm very existed about some of the new features added. Stay tuned.

Posted by Rishi on 17-Mar-10 9:52 PM, 49 Comments

Categories: nRoute, Silverlight, WPF

WP7Sudoku

Sudoku

Couple of weeks ago I had created a Sudoku Game in Silverlight and dressed it up in iPhone's theme, I even posted the code on Codeplex. Now, yesterday with some time on my hand and WP7 expectations running high I took the same codebase and by just changing the main view's XAML in Blend, I re-dressed it in WP7's theme. It's not pixel perfect and the animations need work, but I think we have a reasonable WP7 metro-theme inspired implementation in something that took less than 3 hours of work. Moreover, the iPhone version and WP7 version apart for the visuals are absolutely the same, the backing ViewModel code is without a single change and they both offer the exact same functionality. This is a testimony to both the benefits of a MVVM design (even with games) and also to nRoute framework, upon which both these demos were made.

WP7ViewServices
ViewServices 
View the Window Phone 7 Series Version: http://www.orktane.com/nRoute/WP7Sudoku/
View the iPhone Version: http://www.orktane.com/nRoute/Sudoku/

Note: The WP7 Sudoku demo makes use of "Segoe UI Light" font, and it must be installed on your machine else it will default to the Silverlight's portable font.

Finally, please vote below for which ever design you think is better.

Posted by Rishi on 14-Mar-10 12:20 PM, 31 Comments

Tags: , , , ,
Categories: nRoute, Silverlight, UX

One of the challenges with modern application development is loosely-coupled communication between various independent components within an application; by and large it is not a technical problem, but one of having a common denominator and ensuring that parties to the communication don't entangle each other with dependencies. To this challenge in nRoute we have a messaging framework that decouples application-wide communication using a mediator, against which you can both publish and subscribe without creating direct dependencies. It works much like other mediators such as Prism's Event Aggregator and MVVM Light Toolkit's Messenger, however here the core concept is based around the observer pattern.

Rx's Observer Pattern

As just mentioned nRoute's messaging broker is based on the observer pattern, or more specifically on the Rx-framework's interpretation of the observer pattern vis-a-vie their IObserver<T> and IObservable<T> interfaces. Within our use context, you can think of an Observable as being a publisher and the Observer being a consumer. When the consumer wants to consume, it subscribes to the publisher (via the Subscribe method) and thereon the publisher can do three specific things - push a series of values (of an agreed type T, via the OnNext method), indicate that it is done (via the OnCompleted method) or if an error were to occur relay that (using the OnError method), which also stops the process. Further, when we subscribe we get an invoke-able token (IDisposable type) which the consumer can use to opt-out/unsubscribe from the publisher's output.

ObservingProcess

The other notable thing about the observer setup is that the communication is all one-way, this allows it to multiplex a single published message to more than one subscriber. Now in our broker implementation, we augment the observable with the capability to be able take in a payload and send it to all registered subscribers.

Observable Channels

nRoute's messaging framework implementation uses a "channel" metaphor to describe its observable broker (IObservable<T>) implementation; and each channel is uniquely defined by the type of is payload (ie. type T in IObservable<T>) it carries, and against each channel you can both publish a payload and subscribe for one or more payloads. Code-wise, these channels are nothing more than generic singleton classes that implement the IObservable<T> interface along with a publish mechanism, which as I eluded pushes the payload to all the subscribed IObserver<T> type consumers.

ObservableChannels

As seen above, each channel is represented by the Channel<T> class, which implements IObservable<T> and inherits from the Channel base class, plus the Manager property gives access to the only instance of the singleton Channel<T> class. Further, as class definition shows a Channel<T> class allows for three things, publish a message of type T, publish asynchronously a message of type T, or subscribe to the channel which yields an IDisposable. The Channel base class gives you convenient access to the same three functions, however in both generic and non-generic ways. Note, you do not have to create any channel object yourself and the payload type of T must be a reference type i.e. a class object.

Publishing to any channel couldn't be any simpler, below we look at six ways to publish a log message of type LogInfo both synchronously and asynchronously:

   1: void PublishLog(LogInfo log)
   2: {
   3:     // using the Channel<T> singleton class
   4:     Channel<LogInfo>.Manager.Publish(log);
   5:     Channel<LogInfo>.Manager.PublishAsync(log);
   6:  
   7:     // using the Channel class generic methods (note the generic type is inferred)
   8:     Channel.Publish(log);
   9:     Channel.PublishAsync(log);
  10:  
  11:     // using the Channel class's weakly-typed methods
  12:     Channel.Publish(typeof(LogInfo), log);
  13:     Channel.PublishAsync(typeof(LogInfo), log);
  14: }

The code above should be self-explanatory, with the main take-away being that communication is done via channels, which themselves are defined by the type of the payload they carry. One other notable is that using an observable channel you cannot currently publish an exception (receivable via the OnError method), or indicate the channel is completed (receivable via the OnCompleted method) as a channel remains open through the application's lifespan.

Disposable Subscribers

Given the IObservable<T> channels the subscribers need to be of IObserver<T> type, and build-into nRoute for ease of use sake is an IObserver<T> implementing ChannelObserver<T> class. ChannelObserversThe ChannelObserver<T> basically helps maintain subscription for a channel of type T, and accordingly it has an IsSubscribed property, along with Subscribe and Unsubscribe methods. Also the channel observer class implements IDisposable, so when you are through with it you can just call the Dispose method on it and it will unsubscribe from the channel if required. Additionally the ChannelObserver<T> class also surfaces some additional options like the subscription thread option, or if you would like to have a strongly-referenced subscription (by default all subscriptions are weakly-referenced) and also allows you to optionally provision a delegate-based filter. Below is a simple use snippet, note that you have to explicitly call the Subscribe method to start observing a channel.

   1: // create the observer
   2: var _observer = new ChannelObserver<LogInfo>((l) => ProcessLog(l));
   3:  
   4: // subscribe on the UI Thread
   5: _observer.Subscribe(ThreadOption.UIThread);
   6:  
   7: // and unsubscribe
   8: _observer.Unsubscribe();

I hope the code speaks for itself, as we basically create the channel observer by providing a lambda to handle any incoming log info, and subscribe and unsubscribe as need be. Note, you can subscribe and unsubscribe multiple times using the same observer, as long as you have not disposed the observer. Also, understand that the ChannelObserver<T> class is just a candy-implementation of IObservable<T> which for convenience-sake manages the IDisposable token internally, however you can alternatively furnish any custom implementation of IObserver<T>, so for example:

   1: // subscribe to channel
   2: var _unsubscribeToken = Channel<LogInfo>.Manager.Subscribe((l) => ProcessLog(l));
   3:  
   4: // and to unsubscribe
   5: _unsubscribeToken.Dispose();

Here we are using the Subscribe extension method in nRoute to subscribe by passing in lambda handler, which yields a disposable token that can be used to unsubscribe from the channel. Now if you wanted to subscribe with say threading options, you just need to pass in the observer explicitly as shown below

   1: // create the observer
   2: var _observer = new RelayObserver<LogInfo>((l) => ProcessLog(l), null, null);
   3:  
   4: // subscribe
   5: var _token = Channel<LogInfo>.Manager.Subscribe(_observer, ThreadOption.UIThread);
   6:  
   7: // and to unsubscribe
   8: _token.Dispose();

RelayObserver<T> is a generic implementation of IObserver<T> in nRoute that takes in three delegates for handling a payload, an exception and a notification of completion. And a complementary RelayObservable<T> implementation of IObservable<T> also exists in nRoute, which helps manage one or more IObserver<T> subscribers.

Dedicated Subscribers

In addition to the disposable subscribers, you can also create dedicated subscribers that automatically subscribe and work without any direct user interaction (kind of like services) - and this is sometimes useful when you want to create dedicated sinks for a channel. Lets look at a simple logging example:

   1: [MapChannelObserver(typeof(LogInfo), "IsolatedLogger",
   2:     InitializationMode=InitializationMode.WhenAvaliable,
   3:     Lifetime=InstanceLifetime.Singleton)]
   4: public class IsolatedLoggerSink : IObserver<LogInfo>
   5: {
   6:  
   7: #region IObserver<LogInfo> Members
   8:  
   9:     public void OnCompleted() { .. }
  10:  
  11:     public void OnError(Exception exception) { .. }
  12:  
  13:     public void OnNext(LogInfo value) { .. }
  14:  
  15: #endregion
  16:  
  17: }

So above, just like any subscriber to the LogInfo type channel the IsolatedLoggerSink class implements IObserver<LogInfo>, and additionally we just decorate it with the MapChannelObserver attribute. The mapping attribute is based on the Resource Locator Framework, and it automatically registers an instance of the class as a subscriber to the channel, and also helps manage the lifetime and initialization work - in the case above, we've set the initialization to be done as soon as the resource is available and the lifetime is set to be singleton.

MapChannelObserver

Now normally once you have decorated the class with the MapChannelObserver attribute you don't have to deal with the subscription issue, however incases where you want manual control you can use the ChannelObserverLocator static class shown above - with it you can resolve any registered instance and explicitly consume it.

Threads, Async and Weak-Reference Issues

One of the features of nRoute's messaging framework is that it allows you to publish either on the publisher's working thread or asynchronously on a background thread, and on the subscribers end you can either consume on the publisher's thread, or on a background thread, or on the main UI thread (see the ThreadOption enum type). By default all subscribers use the publisher's thread, and in most cases this works fine but you have to careful (by manually specifying the TheadOption) in cases where the subscriber updates or effects UI controls as it can lead to cross-threading exceptions.  Also when you are consuming or publishing asynchronously there is a non-trivial provisioning overhead associated with sending and receiving the payload asynchronously to each subscriber - so use it selectively, preferably with coarse-grained operations. 

ChannelsThreading

One of the other important notables is that by default internal references to all the subscribers are weakly-referenced, which ensures that if the subscriber falls out of scope/use its subscription is automatically removed on the next publishing cycle. Now, for most cases this has a negligible effect on performance, however in some cases for performance reasons or otherwise you can choose to have a non weakly-reference held, in which case you must explicitly unsubscribe else the subscriber's reference will be indefinitely held by the channel potentially creating memory leaks. In any case, the best practice is to always unsubscribe from a channel when done.

Future Enhancements

In the next drop of nRoute, I'm looking to put in place two main enhancements - first to allow explicit publishing of exceptions, so just as we can publish a payload in a channel we will be able to publish an exception through the same channel. This gels with our normal understanding than any operation can have two possible outcomes, one as defined by the operation's contract and the other being an exception passed through the call-stack. And so in the same vein, in our decoupled pub/sub type of communication we should be able to specifically "raise" (i.e. send) an error explicitly to all the channel's subscribers. The second improvement I seek is to allow "private channels" that can be uniquely indentified and consumed using a shared key, and unlike the public channels, private channels will be temporal so their owners can close them as required. Private channels will functionally be similar to public channels, except they will have to be addressed using their shared key.

Owing to the ongoing development of the Rx-framework, nRoute currently does not have a binary dependency on the Rx-framework, although we have their equivalent IObservable<T> and IObserver<T> definitions present. However, as the Rx-framework stabilizes future iterations of nRoute will take a direct dependency on it, which quite beneficially will bring into play all the operators and observer constructs from Rx.

Summary

So in this post I've covered the ins and out of the nRoute's messaging framework, with the basic outline being it can help decouple your inter-component communication by playing an intermediary role. Now, to press the point further in my next post I'll put an example how in a MVVM setup such mediated communications can play an important role to keep things sane.

Posted by Rishi on 12-Feb-10 2:51 AM, 37 Comments

Categories: nRoute, Silverlight

Cloud Light as you know is a small Silverlight-based runtime that hosts, manages and runs cloud-based applications - and with this post we'll look at how you can either create or port existing Silverlight application to run on Cloud Light. Technically there is not much of a difference between a normal Silverlight application and one that runs in Cloud Light, the main divergence is around around how we "declare" and "define" an application. In Cloud Light all application packages (xap files) are first downloaded then probed for any "declared" applications, once found the corresponding application "definitions" are used initialize the application as required. This business of "declaring" and "defining" applications in Cloud Light is materialized via two interfaces, which is what we'll look into this post by porting the iPhone'ish Sudoku Application (from my previous post) to run in Cloud Light.

Cloud Light SudokuSudoku running in Cloud Light

Declare and Define

So the two interfaces to declare and define a Cloud Light application are IAppMeta and IApp - implementation wise, they are really quite simple, have a look:

IAppIAppMeta

IAppMeta implementation is like a declaration of an application - the Cloud Light runtime looks for IAppMeta implementations, which it then initializes and holds onto. These IAppMeta instances, provides two things, one meta-data info like Title, ShortTitle, and IconPath which is used in the UI (like in the ApplicationBar etc), and second it helps with instances of the application (see the CreateAppInstance method).

In similar vein to the Application class in Silverlight, IApp implementations are Cloud Light definition of an application. And again just like the Application class, it helps with the main visual of application (i.e. RootVisual) - note, in this case it has to be a FrameworkElement derivative. Further, the IApp interface also features call-in methods that are used to notify the application as to when it's starting or closing within Cloud Light (i.e. the AppStarting and AppClosing methods). And somewhat unconventionally, an IApp implementation is also delegated with the  task of showing/hiding the application itself (via the AppShow and AppHide methods) - this sort-of also helps when you want to customize the show/hide animation and when there are Child Windows involved.

Also its worth mentioning that owing to the 10KB limit for designing Cloud Light the application API here is quite minimalistic, for example there is no cancellable mechanism when shutting down an application. Further, application/runtime interaction is also limited, it's not quite feature-rich as you expect with a desktop sort-of an environment.

I (Sudoku) App

Now, given a Cloud Light application's requirements, we'll take the Sudoku application's source-code and in a step-by-step manner port it to Cloud Light (note you can download the source-code for the ported application, it's attached below):

  • Sudoku IconTo start with, we need to add reference to Orktane.AppModel.dll assembly, it contains both the IAppMeta and IApp interfaces. You can download it from the bottom of this post
  • Next, since we are not going to use App.xaml anymore we can just delete it
  • To represent the application in Cloud Light we need to have an icon for it - for this port I've created the one shown on the right. The minimum size required is 64x64 pixels, but you can have something larger as it would just scale down. Note the icon must be in PNG format, as that is the only image format that supports alpha transparency in Silverlight. Obviously, we need to add the icon image to the project, I've added it to a "Resources" folder
  • Now, to define our application we need to add an IApp implementation, for this port I've created one called SudokuApp - and within it we basically serve an instance of the MainPage,xaml as the RootVisual (just like the App.xaml) and when asked to show-hide the application we toggle the Visibility of our RootVisual
  • Next we add an IAppMeta implementation, for this port it's the SudokuAppMeta type - and within its implementation we provide a Title, Short Title, and an assembly-qualified Icon Image path (of the image we embedded), and when asked to create application instance we serve our IApp implementation (i.e. the SudokuApp type)
  • Now, there is one last step, and this is only applicable if you are using nRoute Toolkit (the Sudoku application does). So normally to use nRoute you need to bootstrap it when the Silverlight application starts, but in this case we can't as we don't control the host - to remedy this, I've created an nRoute Toolkit adapted which resides in nRoute.Toolkit.CloudLightAdapter.dll assembly (you can also download it from below), and it allows you to lazily initialize nRoute. However, with the adapter you are also required to individually "map" all the assemblies that make use of nRoute in your application. For example have a look at the SudokuAppMeta class's constructor:
   1: public class SudokuAppMeta : IAppMeta
   2: {
   3:     public SudokuAppMeta()
   4:     {
   5:         nRouteAdapter.Initialize();
   6:         nRouteAdapter.MapAssembly(typeof(SudokuAppMeta).Assembly);
   7:     }   
   8:     // IAppMeta implementation
   9: }

And that's it, we are done porting. Now in some cases depending on your application there might be some aesthetic changes you need/want to make, like for the Sudoku application I've removed the background and put the content in a ViewBox to allow scaling, however I've not added support for dragging the application. 

Installing and Uninstall Apps

Lastly, to install the application you need to use the Console Application, and issue a command like "installapp -url:http://www.orktane.com/Labs/CloudLight/Orktane.Samples.Sudoku.xap" - obviously, substitute the Url with one for your application, but do also remember that the Silverlight's cross-domain communications rules apply. Also if you've got an interesting Cloud Light application, please share it with me and I can put it on the Application-Store listing for everyone to use.

InstallSudoku
And to uninstall an application you can just Ctrl+Shift+Click on the application icon, alternatively you can also use an "uninstallapp" Console based command which takes in a Url just like "installapp" command - so to uninstall the Sudoku application you'll write "uninstallapp -url:http://www.orktane.com/Labs/CloudLight/Orktane.Samples.Sudoku.xap" and then refresh/restart Cloud Light.

Summary

So just to recap, to create/port an application for Cloud Light you need a Xap packaged application with IAppMeta and IApp implementations within it, along with an icon. IAppMeta is like a declaration of application, and IApp is the application definition similar to the Application Class in Silverlight.

Download IApp and IAppMeta assembly (Orktane.AppModel.dll),
Download nRoute Toolkit Adapter (nRoute.Toolkit.CloudLightAdapter.dll),
and Download the source-code for the ported Sudoku Application.

Posted by Rishi on 25-Jan-10 11:43 PM, 26 Comments

Categories: Silverlight, Code, Silverlight

For the Mix10K smart coding challenge, I've create an application runtime that hosts, manages and runs cloud-based applications. The runtime is called Cloud Light, and per the rules of the Mix10K challenge the code and visuals weighs-in less than 10KB. The runtime environment also features an online application store from which you can download and install applications.

Cloud Light ScreenshotView the Cloud Light in the Mix 10K gallery and please vote for it.

Runtime Overview

  • Provides basic window management capabilities like opening, closing, activating, minimizing and restoring of windows
  • Allows you to install applications directly from the web
  • Installed applications information is persistent, with the applications themselves downloaded when the runtime starts
  • Allows you to uninstall applications with a single click
  • You can also install Cloud Light as a Silverlight Out-of-Browser Application (right click and choose "Install Cloud Light.." from the context menu)

Title Bar Overview

The Title Bar shows the active application's title and also show the current date-time. Additionally, it features four buttons on the top-right corner that enable full-screen toggling, showing/hiding of the application store, minimizing of the active application and closing of the active application.TopBar

Applications Store Overview

The online Application Store lists all currently available application in the Cloud. To install any application just click on the entry title, and the application is downloaded and installed - once installed, it should appear in the Application Bar. Going further, more applications will be available through the store.

InstallableApplications

Application Bar Overview

The Application Bar hosts all the currently installed applications, each application getting an icon for itself. The icon also with a highlight represents a running application, and each application can only have one instance running at a go. A single click to an application icon starts the application, if already running it activates it, if previously activated it minimizes it, and if minimized it maximizes and activates it - really simple, right. Also if an application is open, Shift+Clicking the icon closes it and by Ctrl+Shift+Clicking on the icon you can uninstall the application.

AppBar

Extensibility

Apart from the limited applications selection available in the Application Store, you can also create your own applications and install them using the Console application. In a separate post I will detail how you can create your own custom applications and install them.

InstallAppCommandLine

Another simple point of customization is setting the wallpapers, again through the console - so something like "setwallpaper -url:http://adsoftheworld.net/download/windows7/winwall7057_23large.jpg" will change the background into:

CloudLight3

And in addition to the built-in Commands, you can also create custom Console-based Script Commands, and have them automatically register with and be availed through the Console Application (see Silverlight Console).

Summary

So for 10KB worth of c# code and xaml, I think we have a surprising functional runtime that is both extensible and light thanks to Silverlight. It in some-ways can be seen as a prototype for a managed Cloud OS that relies on the Cloud but provides applications in the form we know them today. And in terms of the design it speaks to the simplicity and discoverability that iPhone brought, something that I think needs to be embraced in desktop-applications' designs.

View the Cloud Light in the Mix 10K gallery here
and please vote for it if you like it.

Acknowledgements
Default Grass Wallpaper by Radoslaw Rokita [vathanx@live.com]
Application Icons by Judge

Posted by Rishi on 13-Jan-10 7:38 PM, 39 Comments

Categories: Code, Silverlight, Technology

Following up on Part I which described the workings of the Resource Locator Framework (RLF), in this post we will create a search application that uses the RLF to collate search results from various RSS-feed providers. The RFL will be used to earmark and resolve (at runtime) all the various providers, and results from which will be displayed in a tabular format using a MVVM type solution. Additionally, we'll make use of Rx-framework like Observables to asynchronously gather and compose search results.

ResourceLocatorSampleSmall  View the sample application here and the source code is also available at Codeplex.

Getting The Search Providers Results

In our sample application the provides are essentially search-engines that output results in RSS-feed format, and within our application they are represented by an ISearchProvider interface (shown below). The search results are materialized into the SearchResult type, which corresponds to an RSS-feed item and has Title, Description, Dated and Url fields. Further, for searching a provider takes the search keywords, and returns an IObservable - using which we can have the results asynchronously pushed to us.

SearchProviders

The IObservable/IObserver pairing is also very simple, just to recap for those unfamiliar - you can think of the Observable as the publisher and Observer as the consumer. When the consumer wants to consume, it subscribes to the publisher and the publisher can do three specific things - push a series of values (of an agreed type i.e. type T, via the OnNext method), indicate that it is done (via the OnCompleted method) or if an error were to occur relay that (using the OnError method, which also stops the process). Further, when we subscribe we get an invoke-able token (IDisposable type) which the consumer can (prior to completion) use to opt-out/unsubscribe from the publisher's output.

ObservingProcess 
Now in our case, the ISearchProvider is the publisher, which when asked (using search keywords) publishes a series of search results to which we subscribe. And in our sample we have realized the publishing-consuming using nRoute's build-in IObservable<T> and IObserver<T> implementations called RelayObservable<T> and RelayObserver<T> classes. Below is the outline of ISearchProvider's Search method's implementation which pushes the WebClient's response to the RelayObserver<T>'s  subscribers.

   1: var _observable = new RelayObservable<SearchResult>();
   2: ...
   3: _webClient.DownloadStringCompleted += (s, e) => 
   4: { 
   5:     if (e.Error != null)                      // incase of an error
   6:         _observable.OnError(e.Error);
   7:     else if (e.Cancelled)                     // if cancelled we indicate completed
   8:        _observable.OnCompleted();            
   9:     else {                                    // else, we parse and push the results
  10:         ParseAndPushResults(e.Results, _observable.OnNext); 
  11:         _observable.OnCompleted();            // we also indicate we are done
  12:     }
  13: }
  14: ...
  15: return _observable;                           // return the observable
 
On the other end of the stick, when we want to consume the output of the publisher above we have to subscribe - and for that we can either use a RelayObserver<T> or equally use the Subscribe extension method on any IObservable<T>. So below we are subscribing to the ISearchProvider's Observable and thereon we handle the three possible return cases. Also note the cancellation token (IDisposable) variable which we keep around incase we want to cancel. 
 
   1: var _cancellationToken = _searchProvider.Search(SearchText).Subscribe<SearchResult>(
   2:             (r) => _results.Add(r),                 // on result
   3:             (e) => ShowError(e),                    // on error
   4:             () => _isLoading = false);              // on completed
 
And that's it - we have a bona fide asynchronous communication archetype to handle search results in our ViewModel. The rest of the job just involves monkey code to marshal the results to the UI. Also note, because Silverlight can't directly access web-based RSS-feeds (unless the sources opt-in), we have got local ASP.NET proxies to go with the providers.

Getting The Search Providers Themselves

Given we know how to get the search results, our next step is get the providers themselves - and for that we'll create a specific mapping which locates ISearchProvider resources/providers. With the RLF, my general practice to create explicit mappings in a three step process - first create a meta-data class (if needed), create the IResourceLocator, and third create the mapping attributes. We'll cover these steps point-by-point:

Step 1. Create the Metadata Class 

The metadata is many-times optional but in this case we want to get a Title for the search provider and an Icon (path) to go with that. Plus, for ease of use we also store the name of the provider and the implementation type in the meta-class itself.

   1: public class SearchProviderMeta
   2: {
   3:     public SearchProviderMeta(Type providerType, string name, 
   4:         string title, string iconPath) { ... }
   5:  
   6:     public Type ProviderType { get; private set; }
   7:  
   8:     public string Name { get; private set; }
   9:  
  10:     public string Title { get; private set; }
  11:  
  12:     public string IconPath { get; private set; }
  13: }

I think that was painlessly-simple, but the idea is you should be able to use the meta in a strongly-typed fashion.

Step 2. Create the Resource Locator

As you know a resource locator is just an implementation of IResourceLocator interface, and here we have a very straightforward implementation for the search providers.

SearchProviderLocator

Our search provider's IResourceLocator implementation (DefaultSearchProviderLocator class) shown above is quite simple, it returns an instance of the meta-class we created earlier, it also provides the name of the resource, and by initializing the provider-type it can return instances of the provider. Here actually the implementation of IResourceLocator is numbingly-simple but in other cases the Resource Locator can do all kinds of fuzzy things - it's an abstraction that allows each type of resource or even each individual resource to have its own realization strategy. To give you an example of the fuzziness, the default View Services locator in nRoute can look into the Visual Tree and provide you an instance from there or if applicable a resource can opt to register/unregister an instance of itself as it sees fit (see this post for more info).

Step 3. Create the Resource Mapping

The third and final step is to create an attribute that earmarks the resource as being a search provider, for this we have to derive from the MapResourceBase attribute.

MapSearchProviderAttribute

Above our MapSearchProvider attribute in its constructor takes in the name, title and icon path information, using which it creates the meta-class from Step 1. Next, from the base class we override the GetResourceType method which tells the RLF as to which type of resource we are mapping - the answer of course is ISearchProvider type here. Note, the targetType parameter tells us onto which type this attribute is applied on - which in this case has to be our provider type and we duly check for that. We also override the GetResourceLocator to which we return our DefaultSearchProviderLocator from Step 2 - and this then resides in the Resource catalog for ISearchProvider type. I think it is fairly simple, despite the explicit steps involved - however. if you wanted something more ready-to-eat in that case you can use the MapResource attribute or MapService attribute and forge custom mapping.

Earmarking and Consuming The Providers

We've now got the requisite resource mapping and locating functionality in place, and we can just tack the MapSearchProvider attribute and be off to business, so for example:

   1: [MapSearchProvider("BingProvider", "Bing Search", 
   2:         "/nRoute.Samples.SearchProviders;Component/BingLogo.jpg")]
   3: public class BingProvider : ISearchProvider 
   4: {
   5:     ...
   6: }

Now to individually retrieve the BingProvider instance or its locator you can use the following code, note "BingProvider" is the resource identifier name:

   1: // Gets the resource
   2: ResourceLocator.GetResource<ISearchProvider>("BingProvider");
   3: // Gets the resource locator
   4: ResourceLocator.GetResourceLocator<ISearchProvider>("BingProvider");

However, for use in our ViewModel we are interested in getting all the ISearchProvider types registered - not just one. For that we can access the resource catalog (note, the RLF creates individual catalogs per resource type), and we can also listen to any changes as the catalog implements INotifyCollectionChanged. The Resource<T> is a singleton class that holds the catalog, and the ResourceLocator static class helps with resolving, checking for individual resources or their representative locators.

ResourceCataloging

Using the two classes above we get hold of all the locators, and then rig up columns per-provider to show the results - we make use of the metadata held by the locator to display the icon and title of each provider. The locator also acts like a factory for ISearchProvider instances (per search), which we use to get the search results.

Dynamically Getting More Search Providers

The point of mapping using the RLF is that all the resources are discovered and cataloged at runtime, however the fun doesn't have to stop there. RLF also supports dynamically downloading and mapping all earmarked resources within a DLL or XAP file. To demonstrate that with our sample app, we have a two providers housed in an external DLL which on-demand downloaded and mapped - and because the ViewModel is listening changes to the catalog it is immediately reflected in the UI (try the "+ Provider" button). So to download and automatically map resources we use the RemoteResourceLocator class, have a look:

   1: var _remoteResourceUri = new Uri("nRoute.Samples.SearchProvidersEx.dll", UriKind.Relative);
   2: var _resourceLoader = new RemoteResourceLoader();
   3: _resourceLoader.LoadResource(_remoteResourceUri);
 
Alternatively, you can download assemblies/xap-packages yourself and map each assembly (which is the unit of mapping, as it were) using the AssemblyMapper static class. Note, when we map we not only map the Search Providers but all kinds of earmarked resources like Services, Modules, ViewModels, ViewServices etc.

Summary

The point of this sample application was to show how you can at runtime discover and resolve resources using the RLF. Further, by creating custom resource mapping/locators, we were able to precisely materialize resources along with the metadata associated with each individual resource. The process of creating custom mappings involved creating a meta-class, followed by a resource locator (which owns the materialization strategy), and lastly a mapping attribute which brings together the two. We also have the ability to dynamically load remote resources using the build-in loaders, and any earmarked resources therein are automatically registered.

You can view the Sample App here.
and you can download the Sample App source-code here.

Note, for the sample project be sure to build the nRoute.Samples.SearchProvidersEx before running the project (it sends the DLL to the Web Project) and set the Web Project as your startup project.

Posted by Rishi on 04-Jan-10 10:01 AM, 10 Comments

Categories: nRoute, Code, Silverlight

As the name Resource Locator Framework (RLF) suggests the idea is to locate resources and functionally it's like an IoC type registry. However, it is different from a traditional IoC containers in that it allows each type of resource to put in place its own resource materialization strategy, and two it is designed to be customizable and open-ended as opposed to being internalized and closed-looped. RLF forms the basis of many open-ended features in nRoute like Services, Modules, ViewServices, ViewModels etc - so it's quite extensively used and with this post we'll have an in-depth look at its workings. Additionally, we'll follow this up with a Part II that features an how-to create and use your own custom resources, complete with the source-code.

Resourcing

Like with every IoC registry, the first step is to catalog the resources - with RLF rather than creating a single master catalog, we create individual catalog for each type of resource. As shown in the class diagram below, a resource of type T is represented by a Resource<T> singleton class, which provides a static instance via the Catalog property. The idea with the per type catalog, is to minimize contention and give each and every type of resource maximum flexibility and control.
 ResourceLocators

Within a catalog each resource is represented by an IResourceLocator instance, along with a string-based unique identifier. An IResourceLocator, as seen above, identifies the resource's unique name (ResourceName property, which is also used as the identifier), stores meta-data associated with it (ResourceMeta property), and most importantly can provide an instance of the resource (GetResourceInstance method). Generally speaking, an IResourceLocator is kind of like an individual factory for an individual resource.

With regards to the RLF workings, IResourceLocator is the key abstraction by which each type of resource (or if you require even each individual resource) can provide its own materialization strategy - because when the RLF is asked for a resource it delegates to the IResourceLocator. And within the IResourceLocator you can customize the realization of a resource, so for example with Services in nRotue its locator provides lifetime management, whereas with ViewServices its locator can go through the Visual Tree and look for a resource's visual instance, or with ViewModel's locator it can inject the ViewModel in the View - that's the flexibility that sets the RLF apart from other locators/IoC containers. Also, one can use the IResourceLocator to lazily initialize resources, as using the provided API you can either request for the resource instance or it's representative IResourceLocator instance. Resource<T> catalog, in addition to storing a string-keyed dictionary of IResourceLocator, also implements INotifyPropertyChanged to which you can subscribe for notifications when the catalog changes. It also implements an IEnumerable<string> which enumerates (actually provides a snapshot of) the resource keys currently cataloged. The catalog is thread-safe, which is why the related API also provides a TryGetResource<T> and a IsResourceRegistered<T> checker methods. Also, the Default property in Resource<T>represents the concept of a default resource, which you can retrieve without providing a resource key. Also you can earmark any resource as default, and by convention if one has not been specified then the first registered resource is the considered the default instance; plus if there is no registered resource then the Default property returns a null value.

ResourceLocatorClass

The ResourceLocator static class helps you retrieve and check for any given resource, and it also features non-generic versions of all the resource-querying functions shown above. One other point to remember about resource locators in nRoute is that within a catalog, for any individual resource or entire resource-types, you can put in your custom IResourceLocator implementation it's not locked to any predefined types.

Mapping

Given the catalogs, the next task is to enlist resources into the catalogs - for that nRoute's preferred method is to use attributes to earmark or map resources. There is an assembly-based mapping component in nRoute (described ahead), using which we catalog all resources earmarked by any MapResourceBase derived attribute. The MapResourceBase based attributes are specifically picked up for mapping, and as shown below they yield IResourceLocator instances which are then cataloged.

MappingResources

Specifically, with the MapResourceBase attribute we ask for four things - one, give us the type of resource represented by the attribute (GetResourceType method), two can we initialize the locator immediately (via the CanInitialize method, if not we put it in a pending queue and try it recursively), three is it the default resource (IsDefaultResource property), and lastly help us with an IResourceLocator instance (GetResourceLocator method). Once we have the IResourceLocator instance and resource type, we register it with the specified resource type's catalog (Resource<T>.Catalog).

MapResources

As show above, in nRoute we have various derived mapping attributes for thing like Services, Modules, View-ViewModels etc. By having more specific mapping attributes, we also capture meta-data information so for example with the MapViewService attribute we also gather the lifetime and initialization settings, and that is encapsulated into a ViewServiceMeta class which can be accessed via the IResourceLocator's ResourceMeta property. Having the metadata available within the IResourceLocator, also enables the resource locators to effect the materialization of resources.

Further, just like the many MapResourceBase derived attributes shown above, you can also create your own custom mapping attributes for any resource type. In Part II, we'll go through a step-by-step process of creating a custom mapping attribute. Additionally, as a point of extensibility you can choose to extend, replace or ignore the available mapping-attributes in nRoute and have your custom mapping attributes in play - and this should work with all existing infrastructure without change.

Cataloging

In order to catalog the mapped/earmarked resources we have an AssemblyMapper component, which when given an assembly informs (via an Observable Channel) to all interested components that an assembly is available for mapping - the interested parties can then query for specific attributes against the assembly and act upon them as they please. This is how the MapResourceBase derived attributes are mapped as soon as any assembly is passed-to the AssemblyMapper. Further, the AssemblyMapper keeps a listing of assemblies it has mapped, this way if you choose to selectively check and map resources. Also note normally you don't need to be concerned by the AssemblyMapper, as you will normally just deal with MapResourceBase based mappings.

AssemblyMapperLoader

In addition to the AssemblyMapper we also have a RemoteResourceLoader component that can download and map any DLL or XAP packaged resource - this allows you to resolve and avail remote resources at runtime. Further, like the AssemblyMapper it also keeps track of the remote resources it has loaded or is loading. Note that when a remote resource is downloaded by the RemoteResourceLoader it is automatically subjected to mapping by the AssemblyMapper.

MEF'ed in the Future

For those who know Managed Extensibility Framework (MEF) the similarities with RLF are pretty apparent, especially as MEF targets the same sweet-spot of extensible/open-ended use. However, this is incidental as RLF was made independent of MEF and indeed predates MEF's presence in Silverlight. Nonetheless, for SL4 release I am looking into an update path whereby we can carry forward most of the functionality of what is available in nRoute today, but having swapped the underpinnings to MEF. There is a lot that MEF can add in terms of features, like implicit composition, automatic re-composition and resolving of hierarchal dependencies. However, RLF and MEF don't quite functionally reconcile, specifically because RLF's capability of realizing each resource or resource-type in a custom-to-self manner.

Apart from MEF, it is possible to enhance Resource Locators to play nice with any type of IoC containers - so anything resolved by the locators will go through your specified IoC container. However, this will be one-way traffic as you wouldn't be able to resolve RLF registered resources via your IoC container (circular-dependency issues).

Summary

To sum it up I'll just recap point-wise the basics of RLF:

  • For every resource type, an individual catalog is automatically created (Resource<T>.Catalog)
  • Within a catalog, for each resource we register a representative resource locators (IResourceLocator)
  • IResourceLocator instances capture resource name, resource meta-data and also realize resource instances
  • Using MapResourceBase derived attributes, we can capture all earmarked resource locators using the built-in mapping component
  • You can create your custom MapResourceBase derived mapping attributes
  • And using the RemoteResourceLoader class you can download, resolve and avail remote resources at runtime

And in Part II, we'll put the above into practice - which I think will better enlighten the value of RLF, so do check back.

Update: Part II is up.

Posted by Rishi on 04-Jan-10 4:21 AM, 22 Comments

Categories: Silverlight, nRoute

Consoles are a unique animal in this day and age of multi-touch user interfaces - they stand productively tall despite all the enhancements in user-interaction over the years. And as Silverlight grows into a more rounded and generalized platform, there is a case for Command Line Interface tooling - so here is an attempt at a relatively simple implementation of a Silverlight based Console that includes a Console Window Control and a matching set of extensible Commands Framework that allows for executable commands (called script-actions) vocabulary.

SilverlightConsole3

View the demo application here.
Note, the demo application only supports a limited set of commands, type "help" for listing of available commands, for some examples try "setwallpaper -url:http://adsoftheworld.net/download/windows7/winwall7057_17large.jpg"  or "countdown 00:00:10" or "beep" to make a beeping sound.

Console Window Control (Orktane.Console.dll)

In terms of user-interaction the console is a bit of peculiar control, it isn't exposed as a directly usable control but rather is accessible only through a singular static Console class. For the purposes of the Silverlight Console, I've encapsulated the Console class functionality into an IConsole interface, which in turn is visualized and exposed through a Console Window user-control. The idea of an IConsole interface, just like in Windows, is to enable visually-independent consumption of the console functionality, and at the same time also allow having multiple instances of consoles within a single Silverlight application. Now, Silverlight does have a System.Console class but it is cocooned in the SecurityCritical attribute making it useless outside its internal uses.

ConsoleModel

The IConsole functionality above is much simplified compared to the Windows counterpart, we don't deal with screen-buffers, cursors, or position related settings. Also, though internally we do have In and Out streams they are not exposed, and rather than width-by-height buffer size we deal with a string length output buffer. The simplification is in part because the text-rendering functionality in Silverlight is basically all internal, so we are limited to Textbox or Textblock controls for text-based interaction. However with the RichTextArea control in Silverlight 4, it should enable a much richer experience (see Pose Console in WPF). Further, a solution based on column-by-row screen buffer would have been very resource-heavy for Silverlight, so instead we've used a string-based buffer - which you can set by using the SetOutBuffer method.

One other critical difference between the Windows counterpart is that Silverlight doesn't allow blocking calls, so returning values through ReadLine and ReadKey functionality isn't possible, hence ReadKey and ReadLine calls above return void. In place of returning values, both the ReadKey and ReadLine functionality take in an Action delegate which is used to yield the user input - the ReadKey takes in an Action of ConsoleKeyInfo (shown above) delegate and ReadLine takes an Action of String delegate. Now, whenever you set the ReadKey or the ReadLine delegate it switches the input mode between the two, and whenever you set the delegate it would keep sending the input to the same delegate for each input until changed.

Another issue with using the text-controls in Silverlight is that we have to manually disable input, for which you have to use the DisableInput property on the IConsole interface. This takes away the input Textbox, and if you choose you can display alternate text using the DisableInputText property - so for example below we have disabled the input whilst we are downloading in the background and erstwhile we are showing the progress info using the DisableInputText. Note the red indicator on the left of the text, which visually is a separate area (Textbox actually) from the console output area (also a disabled Textbox).

DisabledInputText 

Now to visually realize the IConsole we have the ConsoleWindow user-control that you can directly use, it has a Console property of type IConsole which allows for procedural use of the console. Internally, we have the console functionality separated from the visuals, a View-ViewModel kind of separation as shown below. You can potentially change the visuals or logic by changing either, or you can create your console-visuals using the ConsoleBase as a starting point.

ConsoleWindowModel

Note, since we are not using a cell based display, in the Console Window we use a fixed-width font, with the width pegged for 80 columns. This aspect is hard-coded, but it is consistent to the default Windows console.

Script-Actions Framework (Orktane.ScriptActions.dll)

By itself the ConsoleWindow implementation is dumb as a stick, it has no concept of executable commands, it just handles the input and output business. And so we have this Script Actions framework (or Commands framework), which basically extends the IConsole to allows execution of custom script-actions, where script-actions are executable commands (note, we don't use the word command because of the ICommand-related conation). In simpler terms you can think of script-actions as extensible vocabulary which is executable in a console. A

ScriptActionsModel

As seen above, we have two types of script-actions, one which can execute by itself (IScriptAction) and the other derivative (IConsoleScriptAction) that requires a console instance to execute. The Execute method takes in an Arguments-type parameter, which is a dictionary of parsed switches and command-line arguments. The command line parser is by Richard Lopes, with some additional word done by Jake Ginnivan. However, for a future release I am looking to port the Command Line Parser Library (by Jakub Malý), which allows for strongly-typed arguments and better structuring of script-actions.

Now, if your ScriptAction class implements the IConsoleScriptAction then the Console instance is passed in and the Initialize method is called prior to execution. And again because we don't have blocking calls in Silverlight you have to manually indicate as to when the script-action has finished its execution, for that you use the ExecutionCompleted event to flag the completion. The close method is called when you've finished, or earlier if the executing environment is itself closing. Further, you can also handle a cancel request (called using the Ctrl+C pairing) by listening to the IConsole's CancelKeyPress event. On the other hand, the IScriptAction based script-action are executed without any indication in the Console (note that is different from when a request command is not found), and once the execution has been called the console returns to an empty console prompt.

On of the features in nRoute, is a MEF like composition component called the Resource Locator - it basically allows you to earmark specific resources and have them cataloged. So based on that, we have a MapScriptAction attribute that flags an implementation of IScriptAction for use in a console; as an example consider:

   1: [MapScriptAction("GC", "GC Memory", 
   2:     ShortDescription = "Forces an immediate garbage collection.",
   3:     Lifetime = InstanceLifetime.PerInstance, UnListed = true)]
   4: public class GCScriptAction : IScriptAction
   5: {
   6:     public void Execute(Arguments args) { 
   7:         GC.Collect();
   8:     }
   9: }

Above, we an IScriptAction implementation that forces an immediate garbage collection on execution, and we have earmarked it with a MapScriptAction attribute. The attribute takes in couple of settings like a unique and callable command-name, a title for the script-action and other options like short-description, a lifetime setting indicating how to handle instantiation, and lastly an option as to if the command is not listed in the help listings. Using the attributes based composition of script-actions makes it painless to have commands availed at runtime or dynamically resourced, for more information please see Introduction to nRoute.Toolkit posts.

Lastly, once we have the script-actions we need to enable their use from within an IConsole instance, for that we have a behavior called ScriptActionConsoleBehavior that attaches to any IConsoleHost implementing (also must be a FrameworkElement) instance. The xaml for that looks like:

   1: <console:ConsoleWindow x:Name="consoleWindow">
   2:     <i:Interaction.Behaviors>
   3:         <scriptActions:ScriptActionConsoleBehavior/>
   4:     </i:Interaction.Behaviors>
   5: </console:ConsoleWindow>

As seen above, the separation of concerns in terms of the console's working-logic and the visuals allows you to plug-in your own custom logic or visual implementation. So for example you could have MEF composed script-actions, or bring Powershell scripts into Silverlight and hook them into a ConsoleWindow. Remember the pairing is necessary, as by itself the Console Window control is dumb-as-a-stick.

Summary

So what we have here is a two-piece solution, one an IConsole based visual control, and two a complimentary console-executable vocabulary of script-actions. And though the solution is not true to the Windows version, it within the limitations of Silverlight a very usable tool. Finally, if you have suggestions or ideas to enhance what's here please do let me know.

Source-code and binaries are available on Codeplex
and you can view the Console Demo Application here.

Posted by Rishi on 29-Dec-09 6:15 AM, 19 Comments

Today I saw a cool article on Code Project on how to do multi-binding in Silverlight using attached properties and a specialized type of value-converter. I though we could do the same thing with Value Converter Relays in nRoute.Toolkit without requiring additional classes/converters. So in this post we'll cover how to easily address multi-binding scenarios (as when you have multiple inputs, but one required output) using value-converter relays in Silverlight.

The Use-Case

The use-case is very simple, we have this form (shown below) that takes in a Person object with three properties namely Surname, First Name and Age - and as you enter them into the form, it updates the title of form with the full name derived from what you have entered. Nothing fancy, but the idea is that we should be able to consume two or more fields through one binding (as in multi-bind).

MultiBindingForm

Value-Converter Relays

Just to reiterate, a relay is like a facade to an actual implementation that can be specified elsewhere such as your code-behind or your ViewModel. In this case, we'll use a code-behind implementation as the requirement is essentially to turn two inputs into a formatted string, and that really is a view-level detail so it should stay there. All the same, if you wanted to use a ViewModel driven implementation then you can use a behaviour named  "BridgeValueConverterBehavior", which as you can guess "bridges" the relay with an implementation from your ViewModel (using bindings).

How-To Steps: Declare, Define and Use

Step 1, we declare the value-converter relay in our UserControl's resources collection, just like any static resource:

   1: <nComponents:ValueConverterRelay x:Key="TitleConverter"/>

Step 2, once we have the relay declared we define it in our code-behind. Here we are using an extension method available in nRoute.Components namespace that allows us to define the value-converter functionality using a lambda statement. Note, it is important to set this before we set the data-context, obviously because it is needed once the data-context is available.

   1: this.SetRelayConverter<Person, string>("TitleConverter", 
   2:     (p) => string.Format("{0}, {1}", p.Surname, p.Forename));

Step 3, to use the formatted string, we just bind to the data-context (which is the Person object) whilst using our value-converter relay:

   1: <TextBlock Text="{Binding Converter={StaticResource TitleConverter}, Mode=OneWay}"/>

And that's it we are done, we have our fake multi-binding in SL using value-converters. However, note there is one niggle, because we are directly setting the Person as our data-context, we have to manually update the data-context on the TextBlock whenever the property changes. This could be avoided by using ViewModels or INotifyPropertyChanged notifications, but since the original sample didn't I've avoided it too.

More Relays

Now that you've see the ValueConverterRelay in action, I'll just mention that we have two other types of relays in nRoute - one called Command Relay and another Value Relay. You can see a Command Relay in action in my recent ICommands related post, and the Value Relay is put to good use in my Web Xcel demo - there I've used it to "pseudo bind" to both a non-dependency property and also to another read-only dependency property. And so to sum it up, consider the use of relays for lot of sticky-stuff like pseudo multi-binding use, binding to data-templates, consuming read-only properties etc. and though it's not pretty it gets the job done.

You can download the value-converter relay project's source code,
note it requires the nRoute.Toolkit which is available on Codeplex,
and the original article on Multi-binding with source is available on Code Project.

Posted by Rishi on 11-Nov-09 2:01 PM, 12 Comments

Categories: nRoute, Silverlight