Nick Randolph and I have been kicking around the idea of adapting the OpenNETCF.IoC project to Silverlight Mobile on Windows Phone 7 (and by “discussing” I mean I’m trying to convince him to do it for me). I just noticed over on the IoC stats page that we’ve had some referrals from someone who apparently has either already done it or is in the process of adapting it for PRISM. I’ve contacted him to see if we might collaborate, but this is exciting news. Having a dependency injection framework right out of the box for phone development can only help the community provide solid applications.
We recently ported a desktop SCSF/CAB application over to use the OpenNETCF.IoC framework. The primary thinking here was that the SCSF has way, way more stuff than we really need, want or use and the SCSF wizards had done wacky things to a few Studio installations, so we wanted to get rid of all of that as well.
I’ve checked in the fruits of the labors into the Codeplex project, including new desktop project and solution files.
Now you can be even closer to one codebase for both desktop and device projects. If nothing else, it allows you to not have to remember two different injection frameworks if, like me, you end up doing a lot of work on both platforms.
Long, long ago I wrote an article for MSDN on creating a multi-Form CF application that used a Form Stack. Since we all tend to grow and learn as developers, we find different ways to do things (and generally we scoff at code we wrote years before as inferior crap).
Well Peter Nowak is giving a presentation of the OpenNETCF.IoC framework next week and I decided that a sample of using the UI elements of the library (Workspaces, SmartParts, etc) might be handy and so I decided to rewrite the Form Stack following my latest thinking. Basically the idea is to allow a user to navigate through Forms (actually Views – you are separating your Views from the Model, right?) like you would on a browser. You can move forward and back as well as “adding” to the end or top of the stack. We also don’t want to be constantly creating new instances of the View classes because we like applications to perform well.
Here’s a look at the new application (yes, I know it’s “developer ugly” but this is about architecture, not aesthetics):
You can see the stack in the list, and our current position is noted by the asterisk. “Fwd” will move down to View B, “Back” will move up to Form A, or you can push a new A or B onto the stack at the current location, which will truncate everything currently above (after) the current position. Again, think of how your browser works. It’s important to know, also, that there are only 3 total View instances created at this point (one of each specific type).
The code for this application is in source control over at the OpenNETCF.IoC Framework Codeplex site. You’ll notice it’s called FormStackCS, hinting that there may be a FormStackVB coming. If you’d like to volunteer to do that port, by all means let me know (meaning don’t hold your breath waiting for me to do it).
Recently I got feedback from Nick Randolph, another device developer MVP, regarding the OpenNETCF.IoC framework and handling the lifecycle of IDisposable objects (well we taked about a few things, but this is the one I tackled first). The problem is that if you add an IDisposable object to any DI container (be it OpenNETCF.IoC, Unity, Ninject or whatever) the container knows nothing about the object’s Disposed state. Unfortunately the IDisposable interface doesn’t expose an IsDisposed property or OnDisposed event.
SO what, exactly, is the problem? Well, let’s assume we create an IDisposable object and add it to the DI container. AT some point later, we’re done with the object, so we call Dispose. Well that internally releases the object’s native resources, but the object itself still has a root (the reference from the container) and so the GC will never actully collect the object and its managed resources. On an embedded device this could be a problem.
The solution that we came up with is to create a wrapper for IDisposable objects and a new set of methods for the container for adding. So now you can do something like this:
var instance = RootWorkItem.Items.AddNewDisposable<MyDisposableType>();
Now instead of this returning an instance of MyDisposableType, it returns a container object that holds it. You access the MyDisposableType object itself via the Instance property of the container, which requires some small code work on the consumer’s part, but the nice thing is that when you call Dispose on that container, it in turn calls Dispose on the contained instance *and* it removes the object from the DI container so the GC can do it’s work on the object.
I’ve not rolled a new framework release with these changes because they really are just a proposed solution for now. If you’re interested, go ahead and pull the latest code from the source code page (change set 32718) on the project site and give it a try. There are a load of new unit tests that show the general idea on usage.
It’s been a while since I did any check-ins to the OpenNETCF.IoC framework. It’s not due to lack of interest or lack of thought on my part. I’ve just been very, very busy lately. We’ve now using the IoC project in a few commercial applications with very good results, so there isn’t a whole lot more to add (though I do want to add some sort of lifecycle management capabilities).
In the hope of getting a little more adoption of the framework, I’ve added an adapter to OpenNETCF.IoC for the Microsoft Patterns and Practices CommonServiceLocator (CSL). You can use CSL code to extract object instances from the Items collection. My hope is that this makes it easier for development teams using CSL to integrate OpenNETCF.IoC into their mobile and embedded projects.
If you have any other ideas or feature requests for OpenNETCF.IoC, by all means submit a request or start a discussion on the project site. And if you’re using it, I’m always interested to see how it’s working out.
I’ve pushed another ode update for the OpenNETCF IoC Framework into Codeplex. Highlights in this one are the fact that I’ve added a WorkItems collection to the WorkItem class, meaning there’s now the potential for parent/child relationships.