在 MEF 中处理多个 Tab 页对应同一模块的不同实例
在 MEF 中处理多个 Tab 页对应同一模块的不同实例时,关键在于控制 实例生命周期 和 导出/导入策略。以下是具体解决方案:
1. 基础场景实现
需求:每个 Tab 页需要独立的 ModuleA
实例
// 模块定义(标记为非共享实例)
[Export(typeof(IModule))]
[PartCreationPolicy(CreationPolicy.NonShared)] // 关键点:每次请求新实例
public class ModuleA : IModule {public string TabId { get; } = Guid.NewGuid().ToString();
}// Tab 页容器类
public class TabPage {[Import(typeof(IModule))]public IModule Module { get; set; } // 每个Tab会注入不同的实例
}// 主程序使用
var tabs = new List<TabPage>();
for (int i = 0; i < 5; i++) {var tab = new TabPage();container.ComposeParts(tab); // 每次都会创建新的ModuleA实例tabs.Add(tab);
}
2. 进阶场景:带参数的实例化
需求:每个 Tab 页需要定制化的模块实例
// 使用 ExportFactory 实现按需创建
[Export]
public class TabManager {[Import]public ExportFactory<IModule> ModuleFactory { get; set; }public IModule CreateTabModule(string title) {var export = ModuleFactory.CreateExport();var module = export.Value;module.Title = title; // 假设IModule有Title属性return module;}
}// 模块定义
[Export(typeof(IModule))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ModuleA : IModule {public string Title { get; set; }
}
3. 生命周期对比
方式 | 特点 |
---|---|
CreationPolicy.Shared | 单例模式(所有 Tab 共享同一实例) |
CreationPolicy.NonShared | 每次请求新实例(适合多 Tab 场景) |
ExportFactory | 更精细的控制,可在运行时传递参数 |
4. 完整 WPF TabControl 集成示例
// MainWindow.xaml.cs
[Export]
public partial class MainWindow : Window {[ImportMany]public IEnumerable<ExportFactory<IModule, IModuleMetadata>> ModuleFactories { get; set; }private void AddTab(string moduleType) {var factory = ModuleFactories.First(f => f.Metadata.ModuleType == moduleType);var export = factory.CreateExport();var tabItem = new TabItem {Header = export.Metadata.Title,Content = new ModuleView { DataContext = export.Value }};tabControl.Items.Add(tabItem);}
}// 模块定义(带元数据)
[Export(typeof(IModule))]
[ExportMetadata("ModuleType", "Chart")]
[ExportMetadata("Title", "数据分析模块")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChartModule : IModule { /*...*/ }
5. 关键问题解决方案
Q: 如何确保模块资源释放?
// 使用 ExportLifetimeContext 管理生命周期
var export = moduleFactory.CreateExport();
try {var module = export.Value;// 使用模块...
} finally {export.Dispose(); // 释放模块及其依赖
}
Q: 不同 Tab 间需要共享某些服务?
// 将共享服务标记为Shared
[Export(typeof(ISharedService))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class SharedService : ISharedService { /*...*/ }// 模块类通过Import自动获取同一实例
public class ModuleA {[Import]public ISharedService SharedService { get; set; }
}
6. MEF2 (System.Composition) 实现
// 使用 MEF2 的共享范围控制
[Export(typeof(IModule)), Shared(Boundaries.TabBoundary)]
public class TabScopedModule : IModule { /*...*/ }// 创建作用域
using var tabScope = container.CreateBoundaryScope(Boundaries.TabBoundary);
var module = tabScope.GetExport<IModule>();
通过以上方式,MEF 可以完美支持多 Tab 场景下的模块实例管理。如果需要更具体的实现细节(如 MVVM 模式集成或异步加载),可以进一步探讨。