Quantcast
Channel: Nybbles, Bytes and Words
Viewing all articles
Browse latest Browse all 5

WinRT, Caliburn.Micro and IoC - Part 1 (Ninject)

$
0
0
I had been preparing to roll out a Windows 8 Store application (a rewrite of an existing Windows Phone app LEAF Buddy) and was trying to find the best components to use together. I like Caliburn.Micro, and it does have a build for WinRT. Unfortunately its SimpleContainer got even more simple in version 1.4.1, and will not auto-create concrete classes! You have to register everything you ever want to resolve.

This left me in the market for a good IoC for WinRT.  I have used Ninject in the past and really like it.  I have also used Unity.  I could really go either way.  I figured I would see how bad it was to use both and if I ran into any issues further on in my project.  To isolate myslef from any future migration issues I decided I would wrap any IoC I used in an IServiceLocator from the CommonServiceLocator project.  This way it should be fairly trivial to switch (as long as I stuck with constructor injection.

First up was Ninject.  I needed a ServiceLocator wrapper, and a CaliburnApplication wrapper.  Well, first I needed an instance of Ninject that would run on WinRT...  If you do what I did, your first stop was NuGet, which fails...

This was packaged 5/9/2012, so it must have been built with the pre-release WinRT build and .Net 4.5 framework.  The latest release on the Ninject download site is from March, 2012, and has an even earlier version number.

Anyway Remo Gloor has code in a github fork with a start towards a WinRT build. You will have to add a few conditional compile directives and fix up 2 or 3 class references, with the biggest part being disabling lightweight code generation... But, it shouldn't take more than an hour to get it compiling.




Once you get a building Ninject for WinRT, you will also need a IServiceLocator wrapper.  Fear not, they do have a .Net 4.5 build of this.

If you have used Caliburn.Micro before you know you would start with a bootstrapper.  But in WinRT you inherit from CaliburnApplication.  Pull down the project source code and you will see a nice clean WinRT sample HelloWorld.  Which also has instructions and demonstrations of Caliburn.Micro WinRT features.



I have a few issues with the application, mainly that it doesn't demonstrate best practices for state persistence.  Personally I think I will use a combination of SuspensionManager from the VS2012 templates to track frame history and transient data, and custom OnSuspend/OnResume code.

I also wonder if they should have played more nicely with LayoutAwarePage.  It has a nice VisualState management wrapper for orientation change and mouse/keyboard calls.  As well as wrapping up page session state using the SuspensionManager.  It's only real big bugbear is the DefaultViewModel and embedded ObservableDictionary.  I think I will definitely want a new base page inherited from something like this.

Finally, on to the topic at hand.  How do you use Ninject in WinRT and Caliburn.Micro.  Well, since I may well be swapping out IoC in the future, to compare and contrast....  I decided to create an intermediary class CaliburnNinjectApplication (and later CaliburnUnityApplication).  Then use it as I normally would with the rest of the Caliburn.Micro instructions.

Here's what I came up with:




public class CaliburnNinjectApplication : CaliburnApplication
{
    IKernel kernel = new StandardKernel();

    public CaliburnNinjectApplication()
    {
        NinjectServiceLocator locator = new NinjectServiceLocator(kernel);
        ServiceLocator.SetLocatorProvider(() => locator);
        //IKernel gets bound by default.  Let's just add a few other variations
        kernel.Bind().ToConstant(kernel as StandardKernel);
        kernel.Bind().ToConstant(locator);
    }

    protected override void Configure()
    {
        base.Configure();
        //IEventAggregator bind here??
    }

    protected override object GetInstance(Type service, string key)
    {
        if (string.IsNullOrWhiteSpace(key))
        {
            return kernel.Get(service);
        }
        else
        {
            return kernel.Get(service, key);
        }
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return kernel.GetAll(service);
    }

    protected override void BuildUp(object instance)
    {
        kernel.Inject(instance);
    }

    protected override void PrepareViewFirst(Windows.UI.Xaml.Controls.Frame rootFrame)
    {
        kernel.Bind().ToConstant(new FrameAdapter(rootFrame));
    }
}

Update: For those interested in a sample implementation where I try to wrap the best aspects of LayoutAwarePage and SuspensionManager into a Caliburn.Micro WinRT project. Check out part 3 of this series.

Viewing all articles
Browse latest Browse all 5

Latest Images

Trending Articles





Latest Images