MEF概念简介及在Silverlight中的使用DEMO

MEF: Managed Extensibility Framework 可以很容的构造可扩展性的应用程序。MEF提供了发现和组合能力,因此你可以选择来加载插件

MEF解决了什么问题?

- MEF赠送了一种简单的在运行时扩展问题。直到现在,任何程序想支持插件模式,需要构建自己的构架。这些插件经常是特定应用的并且不能被多种实现重用的。

- MEF提供了一个标准方式来让程序暴露自己,消耗外部扩展。扩展,是天生的,能被不同的程序重用。然后,一个扩展需要实现特定应用。扩展可以依赖另一个扩展,MEF确保他们以正确的顺序同时被装配(插件的插件)。

- MEF允许在查询和筛选中使用额外的元数据来标记扩展。

核心机制图:

关键词: 导入;导出;装配;提供者;消费者

 

Export:提供者属性标记

- [Export]

- [Export(Type)]

- [Export(string,Type)]

 

Import:消费者标示

 

他们通过CompositionEngine来实现自动的组装。

 

MEF工作方式的要点:

- MEF的核心由一个Catalog(目录)和一个CompositionContainer组成。Catalog负责查找扩展;Contaner负责协调创建和符合的依赖。

- MEF第一个类是ComposablePart。一个ComposablePart提供了一个或多个Exports,也可以依赖于一个或多个由Imports提供的扩展。一个ComposablePart管理可以是Object或给定类型的实例。

- Exports和Imports每个都有一个契约(Contract)。契约(Contract)是Exports和Imports之间的桥梁。一个Export契约由用来过滤的元数据组成。

- 默认MEF Composable Part实现使用Attribute元数据来声明Exports和Imports。这允许MEF来决定哪个Parts,Imports和Exports是完全可用的。

 

MEF在什么地方:C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client

 

MEF DEMO讲解
.NET 4.0中提供了一个MEF框架用于开发支持插件的软件系统,其中Silverlight4也支持MEF。我们的DEMO要实现的功能如下:

用户在访问Silverlight应用程序时,开始只显示一个“初始的简单的”页面,当用户需要时,动态的从Web网站上下载新的程序集,之后,Silverlight客户端应用程序在使用MEF将动态下载的程序集中所包含的页面组件“组装”成一个新的功能增强的页面。

1. 新建一个DynamicComposePage的Silverlight Bsiness Application项目。生成的项目中可以看到\DynamicComposePage\DynamicComposePage\Views\Home.xaml文件,等一会我们将修改此页面实现页面的动态装配

2. 现在我们需要提供一个MEF部件都遵循的接口,为此,向解决方案添加一个“SIlverlight类库”项目:MyPartCotract,并向该项目中添加一个IMyPart接口,为了简单起见,本例不为此添加任何成员,当然了,在实际开发中国可以依据需要为其添加合适的成员。

namespace MyPartContract
{
    public interface IMyPart
    {

    }
}


 

注意:这不是普通的“类库”项目,Silverlight所使用的程序集是重新编写的,与标准的.NET Framework不一样。

3. 下面定义可供动态组合的Silverlight页面组件。

向解决方案中添加一个名为“MyPageParts”的“Silverlight类库”项目,注意在弹出的对话框中要选择为“Silverlight 4”。

然后向MyPagePart项目中添加一个“Silverlight User Control”,取名为“MyEditorControl”,在这个页面中我们放置一个“RichTextArea”控件来充当文字编辑器:

<UserControl x:Class="MyPageParts.MyEditorControl"
    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="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <RichTextBox x:Name="RichTextBox1" Height="100" Width="100"/>
    </Grid>
</UserControl>


现在,需要让此用户控件可以被MEF动态装配,为此,需要完成两个步骤:

(1) 给本项目(也包括前面创建的Silverlight项目DynamicComposePage)都添加对包容了IMyPart接口的Silverlight类库MyPartContract的引用。

(2) 给本项目(也包括前面创建的Silverlight项目DynamicComposePage)都添加对MEF核心程序集System.ComponentModel.Composition.dll的引用,将要负责完成“装配”工作的Silverlight项目DynamicComposePage还需要添加对另一个核心程序集System.ComonentModel.Composition.Initialization.dl的引用。

注意引用类库的位置:C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client

 

(3) 接着是要在支持MEF动态装配的Silverlight 4用户控件的相应代码上,进行Export导出操作:

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 System.ComponentModel.Composition;
using MyPartContract;

namespace MyPageParts
{
    [Export(typeof(IMyPart))] //Export标记,Contract类型为IMyPart类型
    public partial class MyEditorControl : UserControl,IMyPart //由于Export时的type是IMyPart,所以这里也有实现IMyPart接口
    {
        public MyEditorControl()
        {
            InitializeComponent();
        }
    }
}


(4) 现在开发进行“动态装配”的Silverlight页面(位于DynamicComposePage项目Views文件夹中的Home.xaml)。

在页面上放置一个Button用于启动装配工程,另一个TextBlok用于显示提示信息,更重要的是放置一个ContentControl作为部件容器,用于显示动态装配出来的页面部件:

<navigation:Page
  x:Class="DynamicComposePage.Home" 
  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"
  xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
  mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"  
  Style="{StaticResource PageStyle}">

  <Grid x:Name="LayoutRoot">
    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">

      <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">

        <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" 
                           Text="{Binding Path=Strings.HomePageTitle, Source={StaticResource ApplicationResources}}"/>

        <Button x:Name="btnShowEditor" Click="btnShowEditor_Click" Height="20" Width="50" Content="ShowEditor"/>
        <TextBlock HorizontalAlignment="Center" Margin="5" x:Name="txtInfo" Text="说明:点击按钮显示文本编辑器..." FontSize="15"/>
        <ContentControl x:Name="MyEditorContainer" Height="200" Width="300"/>
      </StackPanel>

    </ScrollViewer>
  </Grid>

</navigation:Page>


下面简单介绍一下页面中的关键代码:

首先,我们需要制定Home.xaml页面“需要”一个IMyPart部件,因为,我们给Home类添加以下属性,并且给其附加“[Import]”标记:

        [Import(typeof(IMyPart))]
        public IMyPart myPart { get; set; }


在Home.xaml页面初次显示时,并不加载部件程序集,当用户点击“ShowEditor”按钮后,动态创建一个WebClient对象从Web网站上下载程序集:

        //动态下载程序集并装载
        private void DownloadAssemblyAndCompose()
        {
            //获取程序集的URI
            string uri = Application.Current.Host.Source.AbsoluteUri;
            int index = uri.IndexOf("/ClientBin");//找出根URL
            uri = uri.Substring(0, index) + "/MyParts/MyPageParts.dll";

            WebClient wClient = new WebClient();
            this.txtInfo.Text = "正在下载文本编辑器组件...";
            wClient.OpenReadCompleted += new OpenReadCompletedEventHandler(wClient_OpenReadCompleted);
            //启动异步下载
            wClient.OpenReadAsync(new Uri(uri));
            this.btnShowEditor.IsEnabled = false; //防止用户二次启动下载
        }


 

注意:在本实例中我们假设所有的可装配部件都放在Web网站的MyParts文件夹下,并且假设我们已经知道了要下载的程序集文件名。在实际项目中,我们可以设计一个用于扫描内部文件夹并向Silverlight客户端返回可装配部件的WCF Service,以允许真正“全动态”的装配工作。

上面代码为WebClient的下载完毕事件(OpenReadCompletedEvent)挂接了一个事件响应方法,其中包容了本例最核心的功能代码:

        void wClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            try
            {
                //加载资源
                AssemblyPart part = new AssemblyPart();
                Assembly ass = part.Load(e.Result);
                //创建Catalog
                AssemblyCatalog cata = new AssemblyCatalog(ass);
                CompositionContainer container = new CompositionContainer(cata);
                CompositionBatch bat = new CompositionBatch();
                bat.AddPart(this);
                container.Compose(bat); //装配
                //显示装配好的页面组件
                if (myPart != null)
                {
                    MyEditorContainer.Content = myPart;
                    this.txtInfo.Text = "下载结束,现在您可以编写文档了";
                }
            }
            catch (Exception ex)
            {
                txtInfo.Text = ex.Message;
                btnShowEditor.IsEnabled = true; //如果有异常,允许用户再次尝试加载
            }
        }


上述代码中的关键在于下载程序集完成之后,从流中动态加载陈续集,然后再调用MEF来装配部件。

5. 在Web网站中常见一个专用的部件文件夹MyParts,将包容了可装配部件的程序集赋值到这一文件夹下。先编译一个该项目,然后把\DynamicComposePage\MyPageParts\Bin\Debug\MyPageParts.dll编译好的dll文件复制到MyParts里。

 

运行后的结果如下:

从本实例看到,将MEF和WebClient组件结合起来,可以让我们实现Silverlight页面的“按需下载”和“动态组合”。

 

源代码:  http://download.csdn.net/detail/eric_k1m/5981395

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值