在 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 模式集成或异步加载),可以进一步探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值