I'm working on a port of Robotlegs for Silverlight in background on my spare time since February. As I'm on a Silverlight and C# learning track, I found this would be a great way to practice C# and Silverlight when it also could help the Robotlegs community.
My goal with this post is to give an insight of the project to people who asked me which is its status and real value and if it have chances to reach a final version.
This alpha contains Robotlegs for Silverlight library sources and its Unit Test project. You can launch the Unit Test runner here in live.
I'm currently working on an HelloSilverlight demo which is basically the port of the HelloFlex demo of Robotlegs for ActionScript 3.0. As it's the first real implementation of the framework outside simply passing Unit Tests, it shows that some serious changes and decisions will have to be made before a second alpha in which the demo have to be included.
The project is developed with Microsoft Visual Web Developer 2010 Express Edition so it guarantees that anybody can work on it with a free Visual Studio license. Visual Web Developer allows only to target Silverlight, but the project could easily be imported in Visual C# 2010 Express or Visual Studio 2010 to target WPF applications.
To create this port I used:
- Robotlegs 1.0 as source for conversion
- C# 4.0 as CLR target language
- Silverlight 4.0 as Silverlight target version
- Unity 2.0 as dependency injection container.
- Silverlight Unit Test Framework as Unit Test framework
- Visual Studio 2010 Web Developer Express as project editor
Before starting to work on the port I had to make some choices.
Choosing between Silverlight 3 or 4
Silverlight 4 was still beta at the time I started the project, but I already have worked on it for the PureMVC Silverlight Employee Admin demo.
I knew that Silverlight 4.0 uses C# 4.0 language syntax which is nearest from ActionScript 3.0 syntax than C# 3.0. As an example, in C# 4.0 it is now possible to use optional parameters for methods as in ActionScript 3.0 without to have to create multiple overload to handle each of the possibility. ActionScript developers will immediately understand why this was a smart choice, specifically in Robotlegs which main goal is to remove boilerplate code from applications created by useless overloads just to nullify one or the other argument.
It was also preferable to use Silverlight 4 as it was planned to be out soon. Recently Microsoft included Silverlight 4.0 as an update in Windows Update, Silverlight 4 is now near from 30% market penetration according to riastasts.
Choosing the dependency injection container
My first idea was to port Till Schneidereit's SwiftSuspender to C#. This would have represented an important amount of work. Hopefully I did not have to do this as some C# dependency injection containers were successfully ported to Silverlight.
Ninject seems to be the best choice for Robotlegs as its main goal is to offer a lightweight, simple to use framework for dependency injection to C# developers. This perfectly matches the spirit under Robotlegs. But it does not support C# 4.0 nor Silverlight 4 for now.
Don't worry, Unity is not so complicated as it seems first. And if Ninject for .NET 4.0 goes out, switching from one to the other should be painless.
Note that none of both frameworks support design time dependency injection with XML. Unity only supports it in its Unity For Desktop version. It means that you can't currently use XML dependency injection configuration in Robotlegs for Silverlight.
Differences between Silverlight and ActionScript version
C# and ActionScript 3.0 are event-driven languages, but their event model are different.
C# doesn't use an equivalent to the EventDispatcher class to handle main events operations as ActionScript does. The XAML components API is similar to ActionScript display objects, but it lacks this unified event model.
While porting the framework I chose to create a custom EventDispatcher base class for all the framework elements that use EventDispatcher in the ActionScript 3.0 equivalent. This work pretty well for the moment, but C# developers are used to work differently with events as they have the
event keyword and
+/- operators overloading. It's something that would probably have to change for the final release.
This means that model objects and view objects currently does not have the same Event API. XAML components uses an API with the only two methods addHandler/removeHandler. Framework elements and model objects use the addEventListener/removeEventListener/dispatchEvent API.
This is sad but some basic issues will cause serious problems here:
- XAML components don't implement a common interface for events handling, addHandler and removeHandler are declared in the FrameworkElement class.
- WPF components have event identifiers like the ButtonBase
public static readonly RoutedEvent ClickEventto identify event objects but Silverlight doesn't. On my first insight of this problem it seems that it will complicate a lot the design of a new event API for the Robotlegs Silverlight port.
- It is impossible to create custom RoutedEvent in Silverlight while this is possible in WPF. This means that we cannot share the same Event object between users classes (in Robotlegs framework base too) and Framework Components. This complicate a lot the code needed to handle events in Robotlegs.
Acceptable solutions to make an easy to use framework equivalent to the ActionScript 3.0 should be found, but it will still require some time and specific Silverlight/WPF compromises.
AutoRemove and AutoCreate
Views mapping auto-create and auto-remove features can't work in the Silverlight nor WPF version.
For this to work XAML components need to dispatch some
Event.REMOVED_FROM_STAGE events equivalent to the ActionScript ones. They do with
FrameworkElement.Unloaded, but when fired the event object passed to event handlers does not share the XAML component origin of the event.
I thought to an ugly hack which consists in storing XAML parents chain to identify each component added with MediatorMap.MapView and to search for each removed component in the list when the
Event.REMOVED_FROM_STAGE fire, but it could cause Garbage Collection problems with XAML and probably performance problems too. It is something to test on a real life application though.
Unmap classes from Dependency Injection framework
In the ActionScript version of Robotlegs, the framework intrinsically need to unmap classes and offer users a way to unmap them from the Dependency Injection framework. It's currently not supported by this port as Unity 2.0 doesn't offer any way to unregister types.
This hopefully doesn't affect the way views or command are unmapped by Robotlegs but this could eventually lead to problems in applications that extensively use Dependency Injection even if this shouldn't have to be a show stopper.
Ninject support unbinding of types, this would probably be the better way to support it in Robotlegs for Silverlight too.
Nested types Dependency Injection
This ones refer to Unity again. I don't know if its a bug with Unity or if it's not intended to be supported, but Unity doesn't seem to inject instances of class in types referenced by type target of the injection. For the moment I simply have decided to ignore this problem but it will, for sure, require some investigation.
C# versus ActionScript
The main difference between C# and ActionScript is finally that C# doesn't allow to refer to types directly like we refer to classes objects in ActionScript.
This means that when you wrote in ActionScript:
mediatorMap.mapView( MyView, MyViewMediator );
You have to write in C#:
C# also supports methods overloading which means some methods of the Robotlegs framework can be overloaded, which is cleaner, like here :
/// Unmap a view Type knowing its concrete Type. void UnmapView( Type viewType ); /// Unmap a view Type knowing its fully qualified type name. void UnmapView( string viewName );
- Download the sources of the project
- Browse the Robotlegs for Silverlight branch on github
- Launch a live Unit Test runner session
As you can see, some serious work have been done, but the project still need time and work before reaching a decent final state. I hope to see Ninject working with C# 4.0/Silverlight 4 soon, even if its current repository doesn't seem to move in this way for the moment.
If anybody think that he could help on this project, just clone the project on github and let me know what we could do with!