Upgrading from the Composite Application Guidance for WPF - June 2008
While developing the Composite Application Library included in the Composite Application Guidance for WPF and Silverlight — February 2009, the patterns & practices team was forced to make several changes. The team tried to keep the number of changes to a minimum. However, some changes were unavoidable, either to support Silverlight, to improve extensibility, or to improve understandability of the library. This topic describes how to upgrade a solution from the June 2008 to the February 2009 version of the Composite Application Library and the major changes that you should be aware of if you are considering upgrading to the February 2009 version. The following sections describe the major changes:
- Update Assembly References
- Update Bootstrapper to Use ModuleCatalogs
- Update Namespace References
- Update Class Name
- Update Unit Test Projects
- Update Custom Region Adapters
Update Assembly References
You should first replace the Composite Application Library — June 2008 assemblies with the ones from the Composite Application Library — February 2009. These assemblies are the following:
- Microsoft.Practices.Composite.dll
- Microsoft.Practices.Composite.Presentation.dll
- Microsoft.Practices.Composite.UnityExtensions.dll
- Microsoft.Practices.Unity.dll (version 1.2.0.0)
- Microsoft.Practices.ObjectBuilder2.dll (version 2.2.0.0)
- Microsoft.Practices.ServiceLocation.dll (version 1.0.0.0)
Next, you should delete the Microsoft.Practices.Composite.WPF.dll assembly (it has been renamed to Microsoft.Practices.Composite.Presentation.dll included in the preceding list). You should also update all references in your projects so they reference Microsoft.Practices.Composite.Presentation instead of Microsoft.Practices.Composite.WPF.
After making these changes, recompile your solution.
Update Bootstrapper to Use ModuleCatalogs
Module enumerators were replaced with module catalogs. The module catalogs interface is Microsoft.Practices.Composite.Modularity.IModuleCatalog, and they are responsible for storing the metadata of all the modules in the application.
Note
This change was made to better support retrieval of modules stored in XAP files in Silverlight and to better align with future platform changes.
Replace the GetModuleEnumerator method with the GetModuleCatalog method independently of the module enumerator used.
Depending on the module enumerator used, perform one of the following steps:
If your application uses a StaticModuleEnumerator module enumerator, replace it with a ModuleCatalog module catalog. The following code shows a sample replacement of this.
// This is the code from the Composite Application Guidance for WPF — // June 2008 to specify the moudules that compose the application. protected override IModuleEnumerator GetModuleEnumerator() { return new StaticModuleEnumerator() .AddModule(typeof (ModuleA), "ModuleB") .AddModule(typeof (ModuleB)) ; } // This is the migrated method for the Composite Application Guidance for // WPF and Silverlight — February 2009. protected override IModuleCatalog GetModuleCatalog() { return new ModuleCatalog() .AddModule(typeof (ModuleA), "ModuleB") .AddModule(typeof (ModuleB)) ; }
If your application uses a ConfigurationModuleEnumerator module enumerator, replace it with a ConfigurationModuleCatalog module catalog. The following code shows a sample replacement of this.
// This is the code from the Composite Application Guidance for WPF — // June 2008 to specify the modules that compose the application. protected override IModuleEnumerator GetModuleEnumerator() { ConfigurationStore store = new ConfigurationStore(); return new ConfigurationModuleEnumerator(store); } // This is the migrated method for the Composite Application Guidance for // WPF and Silverlight — February 2009. protected override IModuleCatalog GetModuleCatalog() { ModuleCatalog catalog = new ConfigurationModuleCatalog(); return catalog; }
In the moduleType attribute of each module tag in the configuration file, add the assembly name next to the class name of every module. A sample replacement is shown in the following code.
// This is example code from the previous version of the Composite Application // Guidance for WPF — June 2008. <module assemblyFile="Modules/ModuleB.dll" moduleType="ModuleB.ModuleB " moduleName="ModuleB"/> // This is example code for the updated version of the Composite Application // Guidance for WPF and Silverlight — February 2009. <module assemblyFile="Modules/ModuleB.dll" moduleType="ModuleB.ModuleB, ModuleB" moduleName="ModuleB"/
Replace the StartupLoaded = "false" attribute used when a module is configured to not be initialized when the application starts with the InitializeMode= "OnDemand" attribute, because the startupLoaded attribute is now deprecated.
// This code is from the Composite Application Guidance for WPF — June 2008. <module assemblyFile="Modules/ModuleC.dll" moduleType="ModuleC.ModuleC" moduleName="ModuleC" startupLoaded="false"/> // This is the migrated code for the Composite Application Guidance for // WPF and Silverlight — February 2009. <module assemblyFile="Modules/ModuleC.dll" moduleType="ModuleC.ModuleC, ModuleC" moduleName="ModuleC" InitializeMode="OnDemand"/>
If your application uses the DirectoryLookUpModuleEnumerator module enumerator, replace it with a DirectoryModuleCatalog module catalog. In this case, set the ModulePath property of the module catalog instance to the folder where the modules will be located. The following code shows a sample replacement of this.
// This code is from the Composite Application Guidance for WPF — June 2008 // to specify the modules that compose the application. protected override IModuleEnumerator GetModuleEnumerator() { return new DirectoryLookupModuleEnumerator(@".\Modules"); } // This is the migrated method for the Composite Application Guidance for // WPF and Silverlight — February 2009. protected override IModuleCatalog GetModuleCatalog() { return new DirectoryModuleCatalog() {ModulePath = @".\Modules"}; }
Replace the startupLoaded attribute used when a module is configured to not be initialized when the application starts with the OnDemand attribute, because the startupLoaded attribute is now deprecated. Make sure that you invert the boolean value of the attribute. The following code shows a sample migration of this.
// This code is from the Composite Application Guidance for WPF — June 2008. [Module(ModuleName = "ModuleC", StartupLoaded = false)] // This is the migrated code from the Composite Application Guidance for WPF and Silverlight — February 2009. [Module(ModuleName = "ModuleC", OnDemand = true)]
If you are loading a module on demand in your application, you probably are using the Initialize method of the ModuleLoader service to load a module defined in the ModuleEnumerator. Replace the ModuleLoader instance with a ModuleManager service instance and use the LoadModule method, passing the module name as a parameter. The following code shows a sample replacement of this.
// This code is from the Composite Application Guidance for WPF — June 2008
private void OnLoadModuleCClick(object sender, RoutedEventArgs e)
{
ModuleInfo moduleToLoad = moduleEnumerator.GetModule("ModuleC");
moduleLoader.Initialize( new ModuleInfo[] { moduleToLoad });
}
// This is the migrated code from the Composite Application Guidance for WPF and Silverlight — February 2009.
private void OnLoadModuleCClick(object sender, RoutedEventArgs e)
{
moduleManager.LoadModule("ModuleC");
}
Note
The IModuleEnumerator interface has been removed. If you have a custom enumerator, you need to replace it with one that implements the IModuleCatalog interface. Often, this is done by inheriting from the ModuleCatalog class.
If you made more extensive changes to the module loading sequence, such as your own module loader, you need to review and account for changes in the module loading process in the February 2009 release. See the Module technical concept for details.
Update Namespace References
The Wpf namespace was renamed so every using statement that references Microsoft.Practices.Composite.Wpf or any namespace below that hierarchy (such as Commands or Events) should be replaced with a Microsoft.Practices.Composite.Presentation using statement.
Note
These changes were made to better reflect the purpose of the namespace. Because the Composite Application Library now also supports Silverlight, having Silverlight-supported classes in a namespace named .Wpf would be confusing.
Update Class Name
The CompositeWpfEvent class was renamed to CompositePresentationEvent class. Therefore, all references to this class must be updated. The following sample shows a sample replacement.
// This code is from the Composite Application Guidance for WPF — June 2008
public class FundAddedEvent : CompositeWpfEvent<FundOrder>
{
}
// This is the migrated code from the Composite Application Guidance for WPF and Silverlight — February 2009.
public class FundAddedEvent : CompositePresentationEvent<FundOrder>
{
}
Update Unit Test Projects
When migrating the unit tests solutions from the previous version of the Composite Application Guidance, perform the steps in the following updates to your unit tests solutions:
- Update your assembly references
- Update namespace references
The following interfaces have changed, so you need to update the classes that implement them. This can be easily done by using the Implement Interface option in Visual Studio, keeping the methods and properties you have already implemented. The interfaces that changed and must be updated are the following:
- IUnityContainer
- IRegionManager
- IRegion
Note
While migrating from the previous version of the Composite Application Library, the Regions collection has been changed from an IDictionary collection to a custom collection class named IRegionCollection. This change caused the movement of the method to add a region to the regions collection from the Regions class to the extension class called RegionManagerExtensions.
Keep in mind that a few other methods may be available under a different namespace that need to be imported (by the using statement) into the appropriate client classes.
After making these changes, your unit tests solutions should compile and the tests should pass.
Update Custom Region Adapters
The IRegionAdapter interface and RegionAdapterBase<T> class have changed in the February 2009 release of the Composite Application Library. If you have a custom region adapter that implements or inherits from these, your code needs to be updated.
IRegionAdapter Interface Changes
The IRegionAdapterInitialize method now takes a region name as a second parameter, as shown in the following code.
public interface IRegionAdapter
{
IRegion Initialize(object regionTarget, string regionName);
}
If your adapter implements this interface, it needs to be updated to handle the additional parameter.
RegionAdapterBase<T> Changes
The base RegionAdapterBase<T> constructor has changed to take an IRegionBehaviorFactory. Minimally, your custom region adapter class's constructor will need to be updated to provide the factory. The IRegionBehaviorFactory parameter is usually injected by the dependency injection container during creation of the adapter, so you simply need to add it as a parameter to your class's constructor, as shown in the following code.
public class CustomRegionAdapter : RegionAdapterBase<ContentControl>
{
public CustomRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}
...
}
To learn about region implementation details, including RegionBehaviors, see the "Extending Regions" topic in the UI Composition technical concept.