6.1 KiB
6.1 KiB
Prism Module Pattern
When to Use
- Creating a new feature module that integrates with DataPRO shell
- Adding new UI components that need to be loaded at runtime
- Implementing isolated feature sets that can be developed independently
Files to Create/Modify
1. Module Project Structure
DataPRO/Modules/{ModuleName}/
├── {ModuleName}Module.cs (Module entry point)
├── View/
│ └── {ViewName}.xaml(.cs) (XAML views)
├── ViewModel/
│ └── {ViewModelName}.cs (View models)
├── Model/ (Data models, if needed)
└── Resources/ (String resources, images)
2. Register Module in Bootstrapper
File: DataPRO/DataPRO/Bootstrapper.cs
Add to ConfigureModuleCatalog():
moduleCatalog.AddModule<{ModuleName}.{ModuleClass}>();
Code Template
Module Class ({ModuleName}Module.cs)
using System;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using DTS.Common;
using DTS.Common.Interface;
using Prism.Ioc;
using Prism.Modularity;
using Unity;
[assembly: {ModuleName}Name]
[assembly: {ModuleName}ImageAttribute]
namespace {ModuleName}
{
[Export(typeof(IModule))]
[Module(ModuleName = "{ModuleName}")]
public class {ModuleName}Module : IModule
{
private readonly IUnityContainer _unityContainer;
public {ModuleName}Module(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
_unityContainer.RegisterType<I{ViewName}, {ViewName}>();
_unityContainer.RegisterType<I{ViewModelName}, {ViewModelName}>();
}
public void OnInitialized(IContainerProvider containerProvider) { }
public void RegisterTypes(IContainerRegistry containerRegistry)
{
Initialize();
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class {ModuleName}NameAttribute : TextAttribute
{
public {ModuleName}NameAttribute() : this(null) { }
public {ModuleName}NameAttribute(string s)
{
AssemblyName = AssemblyNames.{ModuleName}.ToString();
}
public override string AssemblyName { get; }
public override Type GetAttributeType() => typeof(TextAttribute);
public override string GetAssemblyName() => AssemblyName;
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class {ModuleName}ImageAttribute : ImageAttribute
{
private BitmapImage _img;
public {ModuleName}ImageAttribute() : this(null) { }
public override BitmapImage AssemblyImage
{
get { _img = AssemblyInfo.GetImage(AssemblyNames.{ModuleName}.ToString()); return _img; }
}
public {ModuleName}ImageAttribute(string s)
{
_img = AssemblyInfo.GetImage(AssemblyNames.{ModuleName}.ToString());
}
public override Type GetAttributeType() => typeof(ImageAttribute);
public override BitmapImage GetAssemblyImage() => AssemblyImage;
private string _name;
public override string AssemblyName
{
get { _name = AssemblyNames.{ModuleName}.ToString(); return _name; }
}
public override string GetAssemblyName() => AssemblyName;
private string _group;
public override string AssemblyGroup
{
get { _group = eAssemblyGroups.{GroupType}.ToString(); return _group; }
}
public override string GetAssemblyGroup() => AssemblyGroup;
private eAssemblyRegion _region;
public override eAssemblyRegion AssemblyRegion
{
get { _region = eAssemblyRegion.{ModuleName}Region; return _region; }
}
public override eAssemblyRegion GetAssemblyRegion() => AssemblyRegion;
}
}
Examples from Codebase
Example 1: SensorsListModule
File: DataPRO/Modules/SensorsList/SensorsList/SensorsListModule.cs:22
[Module(ModuleName = "SensorsListModule")]
public class SensorsListModule : IModule
{
private readonly IUnityContainer _unityContainer;
public SensorsListModule(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
_unityContainer.RegisterType<ISensorsListView, SensorsListView>();
_unityContainer.RegisterType<ISensorsListViewModel, SensorsListViewModel>();
}
public void RegisterTypes(IContainerRegistry containerRegistry) => Initialize();
}
Example 2: GraphModule (DTS Viewer)
File: DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/GraphModule.cs:16
[Module(ModuleName = "Graph")]
public class GraphModule : IModule
{
private readonly IUnityContainer _unityContainer;
public GraphModule(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
_unityContainer.RegisterType<IGraphView, GraphView>();
_unityContainer.RegisterType<IGraphViewModel, GraphViewModel>();
}
}
Example 3: Bootstrapper Registration
File: DataPRO/DataPRO/Bootstrapper.cs:179-220
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<StatusAndProgressBar.StatusAndProgressBarModule>();
moduleCatalog.AddModule<DatabaseServices.DatabaseServicesModule>();
moduleCatalog.AddModule<SensorsList.SensorsListModule>();
// ... more modules
}
Common Mistakes to Avoid
- Forgetting to register module in Bootstrapper - Module won't load
- Not implementing both
Initialize()andRegisterTypes()- Both are required for Prism 6+ - Missing assembly attributes - Module won't appear in UI tiles/menu
- Wrong eAssemblyGroups value - Module appears in wrong section
- Not using interface for View/ViewModel registration - Breaks testability and DI
- Singleton vs Transient - Use
ContainerControlledLifetimeManagerfor singletons, otherwise default is transient - Missing
[Export(typeof(IModule))]- Required for MEF discovery in some scenarios