使用MEF进行Winforms

我有一个使用不同选项卡的winforms应用程序。 我想使用MEF能够添加更多在启动时导入的选项卡。 我很难搞清楚如何去做这件事。

编辑:这是我做的。

我拿了主要的winforms类并将其条带化,以便只有一个TabControl,我通过一个接口向每个TabPage公开。 然后我还创建了第二个接口ITab,我与MEF一起使用以获取tabpage,然后将其添加到主tabcontrol。 要创建一个新的标签页,我只需添加一个新表单,然后向其添加一个tabcontrol并设计标签页。 我将ITab界面添加到新表单并添加以下方法将页面移动到主表单。

public void MoveTabPages(IForm fm) { while (this.tabControl1.Controls.Count > 0) { fm.tab.Controls.Add(this.tabControl1.Controls[0]); } } 

事件委托和所有好东西都可以工作,只要它们只引用表单类中的内容即可。

这是完整的代码。

 //Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace Winforms_Mef { public interface IForm { TabControl tab { get; } } public interface ITab { void MoveTabPages(IForm fm); } public partial class Form1 : Form,IForm { private CompositionContainer _container; [Import] public IEnumerable Tabs { get; set; } public TabControl tab { get { return tabControl1; } } public Form1() { Compose(); InitializeComponent(); foreach (ITab tab in Tabs) { tab.MoveTabPages(this); } } private void Compose() { var catalog =new AssemblyCatalog(typeof(ITab).Assembly); var batch = new CompositionBatch(); batch.AddPart(this); _container =new CompositionContainer(catalog); _container.Compose(batch); } } } //Form2.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.ComponentModel.Composition; namespace Winforms_Mef { [Export(typeof(ITab))] public partial class Form2 : Form,ITab { public Form2() { InitializeComponent(); } public void MoveTabPages(IForm fm) { while (this.tabControl1.Controls.Count > 0) { fm.tab.Controls.Add(this.tabControl1.Controls[0]); } } } } 

在继续之前,我认为您的Compose方法需要清理。 为什么要将容器和目录添加到批处理中?

 batch.AddExportedObject(_container); batch.AddExportedObject(catalog); 

AddExportedObject用于将预先存在的对象实例添加为导出,尝试将容器和目录用作导出没有多大意义

 privat void Compose() { var catalog = new AssemblyCatalog(typeof(ITab).Assembly); var batch = new CompositionBatch(); batch.AddPart(this); var container = new CompositionContainer(catalog); container.Compose(batch); } 

这是一个通用的版本,允许您使用Mef将您的winforms表单换成另一个。 有一个使用Mef公开的IForm接口,它有一个名为public void MoveForm(Form form)的方法,它将新表单复制到旧表单上。

这是代码。

 //// Form1 default form using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace Winforms_Mef { public interface IForm { void MoveForm(Form form); } public partial class Form1 : Form { private CompositionContainer _container; [Import] public IEnumerable Forms { get; set; } public Form1() { Compose(); InitializeComponent(); foreach (IForm form in Forms) { this.SuspendLayout(); this.Controls.Clear(); // wipe out the current version of the form this.ResumeLayout(false); form.MoveForm(this); } } private void Compose() { var catalog = new AssemblyCatalog(typeof(IForm).Assembly); var batch = new CompositionBatch(); batch.AddPart(this); _container = new CompositionContainer(catalog); _container.Compose(batch); } } } //// Form 2 uses Mef to replace Form1 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.ComponentModel.Composition; namespace Winforms_Mef { [Export(typeof(IForm))] public partial class Form2 : Form,IForm { public Form2() { InitializeComponent(); } public void MoveForm(Form form) { this.SuspendLayout(); form.SuspendLayout(); form.AutoScaleDimensions = this.AutoScaleDimensions; form.AutoScaleMode=this.AutoScaleMode; form.ClientSize=this.ClientSize; form.Name=this.Name; form.Text=this.Text; while (this.Controls.Count > 0) { form.Controls.Add(this.Controls[0]); } this.ResumeLayout(false); form.ResumeLayout(false); } } }