CAL Cookbook Part3
So what are Weebits? Well, Weebits are what makes up Weebles and Weebles ares what WidgeNet, Inc. produces. Got it? No matter, it’s all fiction. Think of Weebits as parts(pieces) that are used to make products (Weebles), is that better? In the last article we had added a module to our CAL application and that module included a Weebit data service. We are going to continue with that by adding a presentation layer to the module. This module will then encapsulate everything that is related to Weebits.
We are still dealing with ‘what is a module’, so we are not going to be concerned too much with the UI composition facilities in CAL. We’ll get to those in later articles. I mention that because there will be some areas where we’ll gloss over something that won’t make sense right away.
In a previous article I described how to create an editable listbox. We are going to use that code as the presentation for our Weebit module. You can refer to that article for details on the code but the download sample project also contains all of the code. The way you choose to present data to your user will obviously depend on what it is that you are presenting. I chose to use a listbox but I could have just as easily implemented a master/detail view of the same data. And one of the benefits of using CAL is that I can make that change later and it would not affect the design of the application. Along the same lines, the presentation could also be developed by a different design group which facilitates parallel development.

Since the code for the presentation is described in a previous article I won’t repeat it here. The above figure shows the changes that I made to the solution. As you can see there are two views that were defined, WeebitItemCtl is a UserControl that is used to render the listbox items and WeebitEditorView is the editor window that contains the listbox. Both of these can be seen below in the completed application (for this article).

For each of the views mentioned above there is also an associated viewmodel class in order to implement the separated presentation pattern. If you look at the source for each view and viewmodel there really is nothing there that is specific to CAL. So we need to look at the Initialize() method since that’s where we said the module gets its identity.
public class Weebit : IModule
{
private readonly IUnityContainer container;
private readonly IRegionManager regionManager;
public Weebit(IUnityContainer container, IRegionManager regionManager)
{
this.container = container;
this.regionManager = regionManager;
}
public void Initialize()
{
container.RegisterType(new ContainerControlledLifetimeManager());
container.RegisterType();
WeebitEditorView view = container.Resolve ();
regionManager.AddToRegion("MainRegion", view);
}
}
Ignore the RegionManager for now since it is associated with the UI composition services which we will cover later. For now just note that it somehow manages the view. The first statement you should recognize from the previous article. That’s where the container is controlling the lifetime of the object. By the way, we could have also created an instance of WeebitDataSvc locally and then just have the container pass out references to our instance as needed by the application (you’d use RegisterInstance instead of RegisterType). When would you do that? When you need to have more control over the instancing and release of your object. Perhaps there are some resources that you have to manage.
In the next statement we are registering the WeebitEditorViewModel class with the container. Using this form, the container will create a new instance for each reference needed. And as we saw in the previous article we need to kick-start things since the container won’t create anything until it’s required. So in the next statement we are getting a reference to the WeebitEditorView so we can pass it to the RegionManager. But more importantly so that it gets created.
Now we can start to analyze some of the benefits of CAL. It’s already doing a lot for us even in this minimal application. In the first CAL article we started talking about the problems of code dependencies and how nice it would be if there was a ‘factory’ that would handle the instancing for us and pass out references as needed. Well that’s one of the things that CAL’s Unity container provides for us. In the sample project we are examining, we know that there is an instance of WeebitDataSvc . But we did not create it. We also know that an instance of WeebitEditorViewModel has been created and we had nothing to do with that. And more importantly of all is that all three, WeebitEditorView, WeebitEditorViewModel, and WeebitDataSvc are ‘hooked up’ correctly since the data is being displayed (view needs viewmodel and viewmodel needs dataservice) . And that magic is the dependency injection facility that the Unity container provides. To see the mechanism we look at the constructor signature for the classes.
public partial class WeebitEditorView : UserControl
{
public WeebitEditorView(IWeebitEditorViewModel viewModel)
{
this.DataContext = viewModel;
InitializeComponent();
}
}
The constructor for the WeebitEditorView specifies that it needs a reference to a WeebitEditorViewModel . It uses it to set up the DataContext for the view in order to implement the separated presentation pattern. Since we had registered the WeebitEditorViewModel type with the container it new that before it could create an instance of the view, it needed to create an instance of WeebitEditorViewModel (in order to be able to pass a reference). Likewise if we look at the WeebitEditorViewModel class constructor we see a similar approach.
public WeebitEditorViewModel(IWeebitDataSvc weebitSvc)
{
this.weebitSvc = weebitSvc;
...
}
The definition specifies that it needs a reference to WeebitDataSvc. Again, the container sees that before it can create an instance of WeebitEditorViewModel to pass to the view, it needs to create an instance of WeebitDataSvc in order to pass the reference. So all we have to do is tell the container about the types we have defined and then just include in our constructor declaration any objects that we need and everything is taken care of for us. That’s nice.
Now let’s prove some of the instancing comments we made above. Revise the code in the Initialize() method as shown below.
...
WeebitEditorView view = container.Resolve ();
regionManager.AddToRegion("MainRegion", view);
WeebitEditorView view2 = container.Resolve ();
}
Now set a breakpoint in the constructor for WeebitEditorViewModel and WeebitDataSvc. If you run the application you will see that indeed only one instance of the WeebitDataSvc is created and two instances of the WeebitEditorViewModel as expected.
One final note on the code in the Initialize() method. You may have noticed that I didn’t register a type for the WeebitEditorView yet the container was able to create an instance of it. Apparently it works because there is a dependency defined for the object but I’m not clear as to why it’s so.
So to summarize, you can see that the container has taken care of all the instantiation and reference management for us. All we’ve had to do is register the types and specify any object lifetime requirements that we would like observed. Then all we have to do is indicate in the constructor what object references we need. That’s really powerful in making our application loosely coupled. And what’s more we can get references to any object in any module. The only concern we should have may be in the sequencing order for module declaration and circular references. Both of those have bit me. But we can’t show those at this point since we have only one module. So let’s add some more meat to the application in the next article.
RSS feed for comments on this post. TrackBack URI