前言
通过前面MEF的基础知识的学习,我们已经知道MEF可以在控制台程序中寄宿。MEF还可以在Winform,Silverlight,WPF等应用程序中使用。在接下里的几篇文章中我们就重点介绍MEF是如何在这些应用程序中使用的。本文通过一个例子介绍MEF在Silverlight中的简单应用。
正文
第一步:打开VS新建一个Silverlight应用程序,命名为MEFDemo_SL。一路默认。
完整的Solution结构如下:
在MainPage的设计器中添加一个容器控件,我们这里添加一个TabControl(Name设置为“tcContainer”)。
<UserControl x:Class="MEFDemo_SL.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<sdk:Label Grid.Row="0" Margin="10" FontSize="24" HorizontalAlignment="Left"
Name="label1" VerticalAlignment="Top" Content="在Silverlight中使用MEF示例"/>
<sdk:TabControl Grid.Row="1" HorizontalAlignment="Left" Name="tcContainer" VerticalAlignment="Top"
Width="500" Height="300">
<sdk:TabItem Header="MyTab1" Name="tiTabItem1"></sdk:TabItem>
<sdk:TabItem Header="MyTab2" Name="tiTabItem2">
<Button HorizontalAlignment="Center" VerticalAlignment="Center"
Height="27" Width="100" Content="转到MyTab1"></Button>
</sdk:TabItem>
</sdk:TabControl>
</Grid>
</UserControl>
第二步:添加一个Silverlight类库,命名为“MEFDemo_SL.Contract”。删除默认的class1,新建接口IMyPart。
namespace MEFDemo_SL.Contract
{
public interface IMyPart
{
}
}
第三步:创建扩展控件。主要步骤为:
1. 添加一个Silverlight类库,命名为“MEFDemo_SL.Extensions”;
2. 删除默认类。添加“System.ComponentModel.Composition.dll”和项目MEFDemo_SL.Contract的引用,并在类上标记导出特性[Export(typeof(IMyPart))];
3. 新建用户控件命名为“MyExtension1”,使之实现接口IMyPart。并添加一个富文本控件“RichTextBox”命名为“rtbText”。
<UserControl x:Class="MEFDemo_SL.Extensions.MyExtension1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<Grid x:Name="LayoutRoot" Background="White">
<RichTextBox HorizontalAlignment="Left" Margin="10" Name="rtbTest" VerticalAlignment="Top" Height="400" Width="600" BorderThickness="2" Background="Bisque" FontSize="20"/>
</Grid>
</UserControl>
cs后台代码如下:
using System.Windows.Controls;
using System.ComponentModel.Composition;
using MEFDemo_SL.Contract;
using System.Windows;
namespace MEFDemo_SL.Extensions
{
[Export(typeof(IMyPart))]
public partial class MyExtension1 : UserControl,IMyPart
{
public MyExtension1()
{
InitializeComponent();
}
public void Test()
{
MessageBox.Show("I am Extension1 ");
}
}
}
第四步:操作MEFDemo_SL项目,实现在MainPage中加载扩展部件MyExtension1。
1. 在项目MEFDemo_SL中添加对MEFDemo_SL.Contract的项目引用。
2. 添加对程序集“System.ComponentModel.Composition.dll”和“System.ComponentMdel.Composition.Initialization.dll”的引用。
3. 定义ContractType为IMyPart的导入:
//导入Import
[ImportMany(typeof(IMyPart))]
public IEnumerable<IMyPart> MyParts { set; get; }
//也可以用Import来用,相应的需要在组合的时候就不需要使用foreah了
//[Import(typeof(IMyPart))]
//public IMyPart MyParts { set; get; }
4. 组合,为了使得扩展控件能够被加载我们添加对项目“MEFDemo_Extension1”的引用。下一篇我们会介绍如何动态加载XAP包。MainPage.cs代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MEFDemo_SL.Contract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MEFDemo_SL
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
//第一种组合方式 也可以这么写
//var catalog = new AggregateCatalog(new DeploymentCatalog());
//var container = new CompositionContainer(catalog);
//container.ComposeParts(this);
//第二种组合方式
CompositionInitializer.SatisfyImports(this);
foreach (var part in MyParts)
{
tiTabItem1.Content = part;
part.Test();
}
}
//导入Import
[ImportMany(typeof(IMyPart))]
public IEnumerable<IMyPart> MyParts { set; get; }
//也可以用Import来用,相应的需要在组合的时候就不需要使用foreah了
//[Import(typeof(IMyPart))]
//public IMyPart MyParts { set; get; }
}
}
运行结构如下:
先会弹出一个提示框,证明已经组合成功,并且调用了Extension1的Test方法。然后会打开如下界面
其实上面的功能如果不使用MEF的话,可以使用一下代码实现,由此可见MEF简化了引用类的引用及对象的常见工作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MEFDemo_SL.Contract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using MEFDemo_SL.Extensions;
namespace MEFDemo_SL
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
//第一种组合方式 也可以这么写
//var catalog = new AggregateCatalog(new DeploymentCatalog());
//var container = new CompositionContainer(catalog);
//container.ComposeParts(this);
//第二种组合方式
//CompositionInitializer.SatisfyImports(this);
MyExtension1 ex1 = new MyExtension1();
ex1.Test();
tiTabItem1.Content = ex1;
//foreach (var part in MyParts)
//{
// tiTabItem1.Content = part;
// part.Test();
//}
}
//导入Import
//[ImportMany(typeof(IMyPart))]
//public IEnumerable<IMyPart> MyParts { set; get; }
//也可以用Import来用,相应的需要在组合的时候就不需要使用foreah了
//[Import(typeof(IMyPart))]
//public IMyPart MyParts { set; get; }
}
}