The Enterprise Library team has been hard at work on some of our initial stories. One of the bigger initial stories is what we’ve affectionately call ARC01. I know, very descriptive, so let me explain a bit of what this is about.
The Doublemint Twins
Enterprise Library 4.0 (and 4.1) actually had two ways of locating and building object for its various blocks: through static factories or through a Unity dependency injection container.
Actually, having two approaches to building up objects in Enterprise Library 4.0 was intentional. Honest. Really. I mean it. While it may seem a bit odd, this was an intermediate step to moving entirely to a container approach for Enterprise Library.
This move is important for a number of reasons (and not just because we also wrote the Unity container). First, this is important because the static factory approach does not work well for those people who use containers in their applications and want to be able to get Enterprise Library objects from their container. Second, it is important because the instance factories in Enterprise Library 4.0 are handling things that containers are designed to handle, such as lifetime, location, and object creation. It doesn’t make sense to build and maintain these specifically for Enterprise Library.
Enterprise Library 4.0 took a step towards the container world by providing an approach to
configuring a Unity container with the appropriate Enterprise Library pieces. However, this means that you generally want to use either the static factory approach or the container approach, because objects created in one approach do not work with objects in another approach. We were really maintaining two sets of objects and building strategies (that is, the approach to building up those objects in case we need to rebuild them).
As the final step towards moving to using a single container, we now have the static/instance factories that rely on the same container that you could configure independently.
So you can use the static factories, instance factories, or the container and they will all work together.
While this sounds easy, plugging container B into slot A is not as straightforward as you might think. To start with, Enterprise Library 4.0 relied on many ObjectBuilder internals to build objects and frequently would apply configuration during object creation:
We wanted to use the containers in a more traditional way, namely by providing the configuration ahead of time and then using the container to resolve objects, so now we configure the container the first time something needs to be resolved:
After the container has been configured, the EnterpriseLibraryContainer will directly reference the UnityContainer.
Why Can’t We All Just Get Along?
Aside from making the Enterprise Library story a bit cleaner, moving to a container-based approach has another benefit; it makes it easier to provide support for other containers to work with Enterprise Library. By default, the EnterpriseLibraryContainer provides EnterpriseLibrary objects through a UnityContainer but it does so through the IServiceLocator interface provided by the Common Service Locator project. The Common Service Locator was a join effort of thought leaders and key contributors representing various containers (including Unity, Spring.NET, Castle/Windsor, MEF, StructureMap, Ninject).
The IServiceLocator serves as a plug point for Enterprise Library to work with a container other than Unity. The IServiceLocator only deals with how to acquire object instance, we also needed a way to let a container know how it should be configured to support Enterprise Library without letting Enterprise Library know anything about a specific container. We provide this configuration information in a container agnostic way through a set of TypeRegistrations. Generally, a type registration will contain information about how a type should be built (what constructors and parameter values to use, whether to create them as a singleton or instance each time, and what properties to set on the type). Here’s a typical type registration:
1: new TypeRegistration<Database>(
2: () => new SqlDatabase(
3: ConnectionString,
4: Container.Resolved<IDataInstrumentationProvider>(Name)))
5: {
6: Name = Name,
7: Lifetime = TypeRegistrationLifetime.Transient
8: };
9:
Type registrations are specified as expression trees as it makes them a bit easier to read and they tend to work better when refactoring code. The above registration can basically be interpreted as ‘register a type Database named Name that is mapped to a new instance each time of type SqlDatabase and use the constructor that takes a ConnectionString and an IDataInstrumentationProvider (oh, and by the way, can you pretty please resolve that from the container too?)’.
These registrations are processed by a configurator that knows how to apply them to a specific container. Enterprise Library provides a UnityContainerConfigurator, but you can use any other IContainerConfigurator. The general configuration process looks like this:
Configuring Enterprise Library, given a configuration source and a container configurator can be done like this:
1: var configurator = new UnityContainerConfigurator(Container);
2:
3: EnterpriseLibraryContainer.ConfigureContainer(
4: configurator,
5: configurationSource);
Hopefully this gives you a little deeper understanding of the motivation and content for recent changes in Enterprise Library. In future posts, I hope to go into a bit more depth around how we find type registrations and some of the cleanup we did around instrumentation.
If you have looked at, thought about, dreamed about, forgotten about then suddenly remembered, used, or abused the Composite Application Guidance for WPF or Silverlight, please take our recently released poll to let us know how it has been working for you. We are going to start planning the next release and we would love to hear about what you think is working, not working, and where it should go.
You can find the survey here.
Grigori Melnik has posted a survey on features for Enterprise Library v5. Please take a look and vote on your favorite features.
Many have asked for a Visual Basic version of the Composite Application Guidance for WPF and Silverlight (aka Prism v2). We are pleased to offer the Hands-On Labs and Quickstarts in Visual Basic. While the Composite Application Library is still in C#, the examples of how to use the library are in VB for this.
You can download these from MSDN. Drop us a note on the Codeplex forum if you have any questions or problems.
Erwin has posted on building an Outlook style application. He shows a number of nice features in this that you might find interesting, particularly the UseCaseControllers and the ViewToRegionBinder.
See his post to find out more.
The final two parts are available for the webcast Erwin and I were working on, links to the complete series are available below. This web cast has 4 short videos on building a search aggregator composite application using the Prism library. Through these videos we hope to give you an idea of how to put together a composite application and some of the tools Prism has to offer.
Part I: Basic solution layout and adding a module (10 minutes)
Part II: Visual Composition (10 minutes)
Part III: Implementing the View and Using Services (22 minutes)
Part IV: Decoupled Communication (24 minutes)
The second web cast on building our Prism application is now available on Channel 9.
Erwin van der Valk and I are building a sample Silverlight Prism application to aggregate Digg and Twitters searches. It will look something like the picture below when we’re done:
The first part of our web cast created a shell and the Digg module. In the second web cast, we demonstrate creating regions (named placeholders for views) and adding views into it.
We’ve refreshed the Prism V2 release bits on MSDN due to a couple issues we found and decided were worth updating the bits.
The first problem related to how regions worked with the TabControl. In Prism V1, you could activate a view in a TabControl region, like such:
1: var view1 = new TextBlock() { Text = "Tab1" };
2: var view2 = new TextBlock() { Text = "Tab2" };
3: var region = regionManager.Regions["TabRegion"];
4:
5: region.Add(view1);
6: region.Add(view2);
7:
8: region.Activate(view2);
This would, appropriately, activate view2 with the V1 bits. In V2, the behavior was that the view would not activate. This would clearly make life difficult for those migrating from V1 to V2, so we wanted to fix it quickly.
The second problem relates to a Silverlight update that breaks one of the unit tests looking for Silverlight references.
You can get more details on release page of the Codeplex site.
Erwin van der Valk and I have worked up a four part web cast on building a Prism application. The first of these has been posted to Channel 9, you can find it here.
We kept these intentionally short, about 10-20 minutes, and centered around a single topic. Our hope is this lets you quickly get through some key concepts or pick up where you would like to in the series. The various parts will include creating modules, creating shells and views, UI composition, and services.
If there are other things you'd like to see webcasts on, please leave a request as a comment.
We are very proud to release the Composite Application Guidance for Silverlight and WPF (which we often refer to as Prism V2). This release takes the composite story we developed for WPF and brings it to Silverlight. Additionally, we have some good guidance (and a little tooling) to help with building applications that target both WPF and Silverlight.
What’s new with V2?
- Composite scenarios for Silverlight
- Multi-targeting WPF and Silverlight applications
- Improved UI Composition with support for view injection and view discovery
- Quickstarts and RI for both Silverlight and WPF
- Expanded documentation to include Silverlight-focused areas as well as more details about the MVVM / PresentationModel pattern
Learning More
To download the source and find the latest docs, go to the MSDN landing page.
You can find community forums and issues on the Prism Codeplex pages.
You can get a brief introduction to Prism from Blaine on Channel 9.
Blaine and I also give an overview of Prism posted on Channel 9:
I am also working on a number of getting-started style screen-casts with Erwin, another dev on the project, to help build a complete Prism-based application to help you get started. These will show up on Channel 9 too so stay tuned.
The latest Prism drop is out on Codeplex. You should get it. Right now. Dinner will wait.
The 9th drop is now available for Prism V2 and you can find it here. We are approaching the end of the Prism V2 project, targeting mid-February for the final release. So now’s a good time to download it and take a look.
One of the big items we’re working on is re-skinning the reference implementation. Here is what the new UI looks like:
We’re also focusing on getting the docs completed and have now merged the “new” content with the “old” content (we had just been releasing any new or updated content to make easier for folks to see the changing documents). Here’s a screenshot of part of the contents:
Download the source to checkout the entire help-file with all the contents. Keep in mind that we’re still working to clean up many of the documents to reference any new concepts introduced during Prism V2 development, so there may be some documents that aren’t consistent with the V2 libraries yet.
One of the goals of Prism was to avoid coupling too closely with any particular Dependency Injection container. To that end, the first version of Prism had defined an IContainerFacade that anything from the library side of Prism would interact with and we supplied an adapter for Unity Prism.
It turns out there were a number of people interested in a common definition of a service locator interface that applications, frameworks or libraries could use for a similar purpose. Adapters to specific technologies could then be written once and re-used. To that end, the CommonServiceLocator project was established and a number of folks in the .Net community worked with patterns & practices to help define what this interface would look like.
For Prism, we removed our IContainerFacade interface and started using the IServiceLocator interface offered by this project. As Prism V2 is focusing on both WPF and Silverlight, we had ported this interface to a Silverlight version and we have now posted the Common Service Locator for Silverlight binaries to Codeplex.
Hopefully you will find these useful.
Check out Pablo Galiano’s StickyNotes project. StickyNotes allows you to make a variety of comments to help describe your code, share thoughts about its current direction, or make comments for code reviews.
Prism v2 Drop 8 is now available on Codeplex. In this release, we’ve primarily been focused on moving the reference implementation functionality over since the bulk of the library is now available. We’ve moved over the Watchlist, News, and Buy/Sell modules and views to the Siliverlight version of the Stock Trader Reference Implementation. These pieces were dependent on the commanding functionality and, now that that has been added, we’ve been able to move these to Silverlight.
Commanding Changes
We’ve added a CommandParameter to supply a parameter value to a command in support of some of our RI scenarios, the syntax if similar to that of WPF:
1: <Button Content="Buy"
2: cal:Command.Click="{Binding Path=Value, Source={StaticResource BuyCommand}}"
3: cal:Command.CommandParameter="{Binding TickerSymbol}" />
You will notice the Command.Click syntax has a reference to a static resource for the binding source. This was done to handle situations where the command is offered by the presentation model (or view model, if you prefer) but the visual element invoking it is bound to a deeper element. For example, in the position summary grid we want to be able to buy or sell current positions:
The commands for Buy and Sell are available as properties from the presentation model, but the buttons for buying and selling a row show up in grid row bound to individual positions. Since Silverlight does not have relative source binding we end up binding to a static resource. In the reference implementation, this static resource is an ObservableCommand (which is a derivation of an ObservableObject that we used for connecting region context).
Currently, this static ObservableCommand resource is connected to the presentation model’s command in the view’s code behind (this is less than ideal since it requires some code-behind in the view, we’ll be exploring some ways to get rid of this in future iterations):
1: private void PositionGrid_Loaded(object sender, RoutedEventArgs e)
2: {
3: Debug.Assert(this.DataContext != null);
4:
5: // Because in Silverlight you cannot bind to a RelativeSource, we are using Resources with an observable value,
6: // in order to be able to bind to the Buy and Sell commands.
7: // The resources are declared in the XAML, because Silverlight has StaticResource markup only, so these
8: // resources should be available when the control is initializing, even though the Value is yet not set.
9: Binding bindingBuy = new Binding("BuyCommand");
10: bindingBuy.Source = this.DataContext;
11: ((ObservableCommand)this.Resources["BuyCommand"]).SetBinding(ObservableCommand.ValueProperty, bindingBuy);
12:
13: Binding bindingSell = new Binding("SellCommand");
14: bindingSell.Source = this.DataContext;
15: ((ObservableCommand)this.Resources["SellCommand"]).SetBinding(ObservableCommand.ValueProperty, bindingSell);
16: }
Validation in the Reference Implementation
The other difference between Silverlight and WPF that posed interesting issues is around validation. In the WPF version of the RI we used the IDataErrorInfo, but Silverlight only uses an exception based mechanism and it does not allow you to supply an error ‘template’. We had a couple interesting spikes on this, but we ended up going down the route of the providing some attached properties to capture exceptions for a bound control and storing these in an attached error collection, and then providing attached properties that set control properties based on values in that collection (such as setting the background color or providing a tooltip).
The two values we’re currently providing are OnValidationError.ToggleBackground and OnValidationError.ShowToolTip these are set like this:
1: <TextBox
2: inf:OnValidationError.ShowToolTip="True"
3: inf:OnValidationError.ToggleBackground="Red"
4: Text="{Binding Path=Shares, Mode=TwoWay,
5: ValidatesOnExceptions=True,
6: NotifyOnValidationError=True,
7: Converter={StaticResource stringToNullableNumberConverter}}"
8: />
This will create attached behaviors to set the background to the Red brush and show a tooltip if an attached errors collections contains any errors. The relationship between the control and attached behaviors looks like this:
The ToggleBackground and ShowToolTip attached properties setup their corresponding ToggleBackgroundOnValidationBehavior and ShowToolTpOnValidationBehavior attached properties. In addition, the first attached property also establishes the MonitorBindingValidationErrorBehavior attached properties. Here’s a brief description of what the behaviors do:
MonitorBindingValidationErrorBehavior: Monitor validation errors from the control and update an attached Errors collection.
ToggleBackgroundOnValidationBehavior: Monitor the attached Errors collection and update the background property based on the presence of errors in the collection.
ShowToolTipOnValidationBehavior: Monitor the attached Errors collection and update the tooltip property based on the errors in the collection.
This approach to validation is not meant to be comprehensive guidance around validation in SL and WPF, but we wanted to demonstrate some level of validation that could tie into the mechanisms offered for WPF and Silverlight. We only use the attached property approach in the Silverlight version of the RI, but still use the ErrorTemplate approach in the WPF version of the RI. More in-depth validation guidance is something we plan to cover in a future version or Prism.
Modularity Renaming
We also did a bunch of renaming in the modularity area and a little in the event aggregator area to better reflect in the names what the classes do. The crib-sheet version of the rename is:
| Old Name |
New Name |
| ModuleLoader |
ModuleInitializer |
| IModuleRetriever |
IModuleTypeLoader |
| FileModuleRetriever |
FileModuleTypeLoader |
| XapModuleRetriever |
XapModuleTypeLoader |
| CompositeWpfEvent |
CompositePresentationEvent |
I hope this helps in understanding the latest drop and let us know if you have questions, thoughts or comments via the codeplex forum or via comments in this blog.