Agile .NET

Ideas & Gotchas

SCSF – Loading modules into child WorkItems

Posted by Vlad on September 20, 2007

The Composite UI Application Block (CAB) used in the Smart Client Software Factory (SCSF) allows you to specify which modules will be loaded using an XML file or a web service. The problem is that all the modules you specify get loaded into the root WorkItem. If you have a services module, for example, that is used only by one WorkItem, you have to choose between loading it in the root WorkItem and explicitly loading it in the “AddServices” method of your WorkItemController.

The first option can generate EventBroker problems – all events published by the service will be visible to all WorkItems and vice versa, so you might get some “surprise” event calls.

In the second option you get a tight coupling between the module and its services (not always a real problem, but if you have the service in a separate assembly it could be because you are trying to isolate change between them).

The solution we want is to use the same mechanism as the root WorkItem and load the modules defined in an XML file. One way to do this is to create a service that will be available to child WorkItems.

Add the service interface to the Infrastructure.Inteface project:

public interface IModulesFromFileLoaderService

{

void LoadModules(WorkItem workItem, string catalogFilePath);

}

Then add the service implementation to the Interface.Library project:

public class ModulesFromFileLoaderService : IModulesFromFileLoaderService

{

private IModuleLoaderService _moduleLoaderService;

public ModulesFromFileLoaderService([ServiceDependency] IModuleLoaderService moduleLoaderService)

{

_moduleLoaderService = moduleLoaderService;

}

#region IModulesFromFileLoaderService Members

public void LoadModules(WorkItem workItem, string catalogFilePath)

{

XmlStreamDependentModuleEnumerator modEnumerator = new XmlStreamDependentModuleEnumerator();

ProfileCatalogModuleInfoStore infoStore = new ProfileCatalogModuleInfoStore();

infoStore.CatalogFilePath = catalogFilePath;

modEnumerator.ModuleInfoStore = infoStore;

if (modEnumerator != null)

_moduleLoaderService.Load(workItem, modEnumerator.EnumerateModules());

}

#endregion

}

Register the service:

public abstract class SmartClientApplication<TWorkItem, TShell> : Microsoft.Practices.CompositeUI.WPF.WPFFormShellApplication<TWorkItem, TShell>

where TWorkItem : WorkItem, new()

where TShell : Form

{

protected override void AddServices()

{

base.AddServices();

RootWorkItem.Services.AddNew<ProfileCatalogModuleInfoStore, IModuleInfoStore>();

// …

RootWorkItem.Services.AddNew<ModulesFromFileLoaderService, IModulesFromFileLoaderService>();

}

}

And use it in your module initialization:

WorkItem.Services.Get<IModulesFromFileLoaderService>().LoadModules(WorkItem, “ModuleProfileCatalog.xml”);

Another way to implement LoadModules (more details here) is to use FileCatalogModuleEnumerator from Microsoft.Practices.CompositeUI.Services namespace – its simpler, but is works only with V1 schema files (no sections and dependencies).

public void LoadModules(WorkItem workItem, string catalogFilePath)

{

FileCatalogModuleEnumerator modEnumerator = new FileCatalogModuleEnumerator(catalogFilePath);

if (modEnumerator != null)

_moduleLoaderService.Load(workItem, modEnumerator.EnumerateModules());

}

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>