Some time ago I started wondering about mocking and IOC in Silverlight 2. There is quite obviously a gap here that someone needs to plug, as soon as you start writing tests (thank you Jamie Cansdale!) you're going to need mocks of some sort and as soon as you have a Silverlight project of any real size, IOC becomes necessary.
Mark Monster blogged about what it would take to port Castle DynamicProxy and consequently Moq to Silverlight and so until someone comes along with a better or official solution I decided to take up the challenge. There was a fair amount of work, although in terms of actual code changes that were needed due to API changes in the Silverlight CLR there was really very little, the brunt of the work as Mark pointed out was around the lack of Remoting and also the lack of non-generic collections in Silverlight. I will just note though Mark, your list of code changes required to get these projects to compile is a MASSIVE underestimate, because the compiler shows as many errors as it can, but only when you fix these does it throw another few hundred at you!
There was a lot of code in the Castle libraries to support remoting and serialization for remoting (MarshalByRefObject, ISerializable, IDeserializationCallback, SerializableAttribute etc etc), none of this is actually required for any of the core features and aren't supported in Silverlight and so I ripped it all out! The other big chunk of work was that there were hundreds upon hundreds of references to types which are missing in Silverlight 2, generally it was non-generic collections such as ArrayList and Hashtable, but also there were some key threading classes which were absent. I solved this by creating a new assembly called FlawlessCode.MissingTypes and adding into this implementations for the missing types. No, I didn't write them all! What I did do was download the Mono source code and use their implementations! You may notice I changed the namespace of all the Mono types to start with FlawlessCode and not System, this is because some of these collections are implemented internally in the Silverlight CLR but just aren't exposed for our use and Visual Studio was complaining to me.
There were some other changes required in the Castle libraries for features which would make no sense and could never work on Silverlight, these of course were removed. Castle DynamicProxy has the ability to save generated assemblies to disk for example, and Castle Core has types like FileResource and UncResource. None of these will ever work in the way intended because Silverlight doesn't have proper access to the file system.
Moq by comparison was very very easy to port, the only real problem was the HastSet<T> class which is not available, thanks go out again to Mono for this!
In terms of IOC, I also ported the Castle MicroKernel. This should give you the basics to play around with, but I have NOT ported Castle Windsor, the reason being that there is a lot of Xml handling code contained therein and it uses XmlNode, XmlElement, XmlDocument etc... this would all need changing to XNode, XElement, XDocument and the like, to be honest I was tired and thought I'd done enough!
To cut a long story short, all the unit tests now pass! I just want to thank the people who made all this possible in the first place, Jamie Cansdale for the Silverlight NUnit work, the people behind the excellent Castle Project, the people behind Moq and of course the Mono Project. I want to be clear that I'm posting this here as a stopgap solution so that all the people working with the beta of Silverlight 2 have something to play with and to perhaps show that this is possible, but really I'm hoping this will be worthless very soon and that someone who really knows what they're doing does a real port or that we get official support from Moq and Castle.
One issue I do know about with all this, Assembly.GetName which is used by DynamicProxy is marked as SecurityCritical, and as such stops the whole thing from working at all! This would be a disaster and indeed if you were wanting to run Moq or DynamicProxy in the browser it is a disaster, however the way in which Jamie got NUnit to work was by making Visual Studio load the silverlight DLLs using the desktop CLR, and apparently when doing this, the desktop CLR takes no notice of SecurityCritical. The end result is that DynamicProxy works fine using Jamie's unit test templates, but if you reference DynamicProxy from your silverlight app and expect it to run in the browser, it won't.
DISCLAIMER: For what it's worth, I'm not a legal mind and while I don't think I'm doing anything wrong by mashing together all this different open source code, if I'm violating anyone's licenses please give me a heads up before you unleash the hounds and I will of course pull it down immediately.
DISCLAIMER 2: While this all seems to work so far and the unit tests do all pass, I did monkey around with the code quite a bit, so please take this as it comes and don't expect too much!
Download
Castle-SLandMoq-SL.zip (770.03 kb)