This is the sixth post in a series. The other post include:
- Converting the Composite Web Application Block to Unity - Intro.
- Converting the Composite Web Application Block to Unity - Adding an ICompositionContainer
- Converting the Composite Web Application Block to Unity - Clean Up ICompositionContainer
- Converting the Composite Web Application Block to Unity - Ummmm...Oooops.
- Converting the Composite Web Application Block to Unity - Actually Adding Unity
If you want background, go read the earlier posts.
Based upon feedback, I am making the source code available at CWAB and Unity.
For those who have been following along, you all know I am making this up as I go. So, I am asking that you be patient with me as we figure this out together. This article (in particular) may have a few false starts, and "ooops" moments. We are replacing something that was not meant to be pluggable, and all of the refactoring work that has been done up to this point may not be enough.
Reminder: This is a proof of concept. The version of CWAB I am creating here is not a supported product or guidance from patterns & practices. If you really want Unity support in WCSF, please go to the Issue Tracker on the WCSF Community Site and vote for the work item to get Unity support for WCSF.
At the end of the last post I planned on trying to actually use the UnityCompositionContainer, and then nuke the old CompositionContainer.
Let's get started by replacing any calls that creates a CompositionContainer with code that creates a UnityCompositionContainer. There is ONE spot, in WebClientApplication. Simple. Change, recompile, re-run unit tests, and we are green.
If it really was that simple, we should be able to remove the CompositionContainer class (and its test fixture) from the solution, and not have any challenges. Let's try that.
We fail to compile. Our TestableRootCompositionContainer is part of the problem. MockContainer in ManagedObjectCollectionFixture is the rest of it.
If we derive TestableRootCompositionContainer from UnityContainer, and remove everything from the class (as a temporary measure), we go from two to 27 build errors.
<timewarp duration="an or two"/>
Not good. But not too bad, considering what comes next. After fixing these build errors, I got on a roll, and did the following:
- Removed references to the old ObjectBuilder.dll in both unit test and system projects
- Removed the BuilderStrategies folder in both unit test and system projects
- Removed the Collections folder in both unit test and system projects
- Removed the ObjectBuilder folder in both unit test and system projects
- Removed the ProviderDependencyAttribute and its fixture
- Removed StateDependencyAttribute and its fixture
- Removed OptionalDependencyAttribute and its fixture
- Removed ServiceDependencyAttribute and its fixture
- Removed all references to the old ObjectBuilder namespace
- Replaced any [CreateNew] attributes with the Unity [Dependency] attribute
- Hacked on WebClientApplication
- Removed the Services collection. Replaced calls to container.Services.Add with container.RegisterType. If needed added a call to container.Resolve, when the Services.Add call was supposed to return an object.
Ok, things are compiling again. Finally. But there are a few failing unit tests, about 20 or so... Let's fix those.
<type... type.... swear.... type />
Getting those test to pass was fairly simple. All of them required a little bit of container setup that was different than before. This was not a big deal.
There is one major change I did make in the process, and a related renaming. First, the renaming, Page became InjectablePage; MasterPage became InjectableMasterPage, and guess what UserControl became? Excactly, InjectableUserControl. These are better descriptions and will remove the confusion I have dealt with on the forums where people use the wrong Page base class. The other change is that, previously CompositionContainer had two Builders: one for things like services that stayed around, and another for Pages and transient items like presenters. We no longer need two builders, and can get containers and lifetime managers to handle the differences. The approach I took for simplicity is to have each page create a container that is a child of the correct Module container, use this for doing injection on the page, and then nuking the container on Page.Dispose. This is quick and dirty, and it works, but I may revisit it later.
Now, since Unity 1.1 just shipped, it is time to upgrade. I replaced the binaries and...
Everything still passes.
I think that is enough for today.
As a quick check, I just looked at the solution statistics for the original version of CWAB and the current solution. CWAB went from 26KLOC (pre-article one) to 14KLOC, both numbers including unit tests. And I bet that there is more to be cut out and cleaned up. Having a purpose built, re-usable component for DI helped a lot here. For this edition, windiff will probably be the best bet for following all the types of changes I made. This one took a while and impacted a lot of code.
Next, I am going to review unit tests, run code coverage, determine if there are gaps in test coverage after all the hacking. After that, it will be porting one of the quickstarts over to the new version of CWAB. After that, the RI, at which point I will be sure that the updated version works well enough to be a good proof of concept.