Silverlight-MEF-DEMO-擴充電腦的功能

來源:互聯網
上載者:User

“託管擴充性架構(Managed Extensibility Framework,簡稱MEF),是微軟.NET架構下為提高應用和組件複用程度而推出的,用於使組件能夠最大化的重用。使用MEF能夠使靜態編譯的.NET應用程式轉換為動態組合,這將是建立可擴充應用、可擴充架構和應用擴充的好途徑。它將做為.NET Framework 4.0的組成部分之一發布。現在,MEF也將被包含在Silverlight 4.0中。

 
那麼MEF是怎樣工作的呢?簡單分為三個步驟:

•Export (輸出)
•Import (輸入)
•Compose (組合)
簡短說一下MEF的工作原理,MEF的核心包括一個catalog和一個CompositionContainer。category用於發現擴充,而container用於協調建立和梳理依賴性。每個可組合的Part提供了一個或多個Export,並且通常依賴於一個或多個外部提供的服務或Import。每個Part管理一個執行個體為應用程式運行。

 

下面我們做一個小型可擴充計算機樣本來解釋這三個過程

1.首先下載MEF架構套件,Silverlight 4.0會內建,不過微軟已經將其開源了。
http://www.codeplex.com/MEF
2.建立一個Silverlight Navigate Application ,並添加程式集引用(MEF_Beta_2\bin\SL目錄下 System.ComponentModel.Composition.dll)
在項目下添加兩個類檔案Package.cs和PackageCatalog.cs,這兩個檔案在最新的MEF版本中沒有提供,主要用於載入silverlight的Xap包。
這兩個檔案在MEF架構的Sample中提供了(MEF_Beta_2\Samples\PictureViewer\PictureViewer.Common),將這兩個類的存取修飾詞改為public, 添加後注意修改命名空間。
3.修改Home.cs 類

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.ComponentModel;

namespace MefDemo
{
    //用於更新介面的委託
    public delegate void OperateHandler(IOperate Op);

    /// <summary>
    /// 運算器介面
    /// </summary>
    public interface IOperate
    {
        double Op(double left, double right);
        string Symbol { set; get; }
        string Label { get; set; }
    }

    /// <summary>
    /// 加法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class AddButton : Button, IOperate
    {
        [Import("AddButtonContract",AllowRecomposition = true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("AddSybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left + right;
        }

        #endregion

        public AddButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }

    /// <summary>
    /// 減法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class SubButton : Button, IOperate
    {
        [Import("SubButtonContract",AllowRecomposition=true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("SubSybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left - right;
        }

        #endregion

        public SubButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }

    /// <summary>
    /// 為每個運算器的屬性提供值
    /// </summary>
    public class ComponentAttributeProvider
    {
        [Export("AddButtonContract")]
        public string AddLabel  { get { return "Add"; } }
        [Export("AddSybomContract")]
        public string AddSymbol { get { return "+"; } }
        [Export("SubButtonContract")]
        public string SubLabel  { get { return "Sub"; } }
        [Export("SubSybomContract")]
        public string SubSymbol { get { return "-"; } }
    }
}
4.修改 Home.xaml

代碼

<navigation:Page x:Class="MefDemo.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"
    Title="Home"
    Style="{StaticResource PageStyle}">

    <navigation:Page.Resources>
        <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </ItemsPanelTemplate>
    </navigation:Page.Resources>

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

            <StackPanel x:Name="ContentStackPanel" Background="Black">
                <StackPanel   Orientation="Horizontal" Width="455" Height="89" Margin="91,0,91,-30">
                    <TextBox x:Name="LeftNum" HorizontalAlignment="Left"   VerticalAlignment="Center" Width="83" TextWrapping="Wrap"/>
                    <TextBlock x:Name="Symbol" Width="62" Text="+" TextWrapping="Wrap" FontSize="24" Foreground="#FFF80606" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                    <TextBox x:Name="RightNum" HorizontalAlignment="Left"   VerticalAlignment="Center" Width="78" TextWrapping="Wrap"/>
                    <TextBlock Width="64" Text="=" TextWrapping="Wrap" Foreground="#FFF20808" FontSize="21.333" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                    <TextBox x:Name="Result" HorizontalAlignment="Left"   VerticalAlignment="Center" Width="146" TextWrapping="Wrap"/>
                </StackPanel>
                <ListBox x:Name="operateList"  ItemsSource="{Binding}" ItemsPanel="{StaticResource ItemsPanelTemplate1}" Height="99" Background="{x:Null}" BorderBrush="{x:Null}"/>
        <Button x:Name="DynamicLoadButton" Height="40" Width="196" Content="DynamicLoadOperate"/>
            </StackPanel>
        </ScrollViewer>
    </Grid>

</navigation:Page>

5.建立類 OperatorComponent.cs

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.ComponentModel;

namespace MefDemo
{
    //用於更新介面的委託
    public delegate void OperateHandler(IOperate Op);

    /// <summary>
    /// 運算器介面
    /// </summary>
    public interface IOperate
    {
        double Op(double left, double right);
        string Symbol { set; get; }
        string Label { get; set; }
    }

    /// <summary>
    /// 加法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class AddButton : Button, IOperate
    {
        [Import("AddButtonContract",AllowRecomposition = true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("AddSybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left + right;
        }

        #endregion

        public AddButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }

    /// <summary>
    /// 減法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class SubButton : Button, IOperate
    {
        [Import("SubButtonContract",AllowRecomposition=true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("SubSybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left - right;
        }

        #endregion

        public SubButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }

    /// <summary>
    /// 為每個運算器的屬性提供值
    /// </summary>
    public class ComponentAttributeProvider
    {
        [Export("AddButtonContract")]
        public string AddLabel  { get { return "Add"; } }
        [Export("AddSybomContract")]
        public string AddSymbol { get { return "+"; } }
        [Export("SubButtonContract")]
        public string SubLabel  { get { return "Sub"; } }
        [Export("SubSybomContract")]
        public string SubSymbol { get { return "-"; } }
    }
}

 

6.運行。 這樣就構建了一個簡單的運算器,其中的Export、Import就像一個個管道一樣相互串連。
 

7.按照這樣的設計,我們想要對其進行擴充,就必須把介面分離。建立一個Silverlight ClassLibrary Project(Named ContractLibrary),這個Library用來封裝所有的擴充介面,定義Import/Export契約。
現在把原項目中的OperatorComponent.cs 類中的介面遷移到Library項目中,建立類檔案OperateContract.cs 。

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ContractLibrary
{
    public delegate void OperateHandler(IOperate Op);

    /// <summary>
    /// 運算器介面
    /// </summary>
    public interface IOperate
    {
        double Op(double left, double right);
        string Symbol { set; get; }
        string Label { get; set; }
    }
}
編譯通過後在Silverlight主工程(MefDemo)中添加對ContractLibrary項目的引用
8.再建立一個Silverlight ClassLibrary Project (Named StaticExtension),,這個工程就是我們用來靜態擴充的DLL。
a). 在工程下建立我們的運算器類,AddButton.cs , SubButton.cs.(代碼不變).
b). 但注意要添加對ContractLibrary項目的引用和MEF的框架組引用) 。
c). 添加全域屬性配置類(ComponentConfiguration.cs)
d). 刪除主工程中的ComponetOperater.cs.
e). 添加對StaticExtension的引用.
 

9.OK,這樣我們就可以任意擴充運算器,添加更多的擴充運算了。

10.那麼下面是添加一個新的乘法運算所要做的工作。
在StaticExtension中添加新類 Multiply.cs

 

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using ContractLibrary;

namespace StaticExtension
{
    /// <summary>
    /// 乘法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class MultiplyButton : Button, IOperate
    {
        [Import("MultiplyButtonContract", AllowRecomposition = true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("MultiplySybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left * right;
        }

        #endregion

        public MultiplyButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }
}

 

11.上面的是靜態載入,那麼現在我們使用MEF實現動態擴充運算器。傳統型程式的動態擴充是動態載入DLL,而對於Silverlight的Web程式則是動態載入Xap包了。
建立普通Silverlight Application(Named DynamicExtension).

 
去掉勾選Add a test page that references the application.
1). 刪掉App和Main等不必要的檔案,只留一個空的Silverlight項目,以減少Xap包的大小。
2). 添加ContractLibrary和MEF框架組的引用(可以將引用程式集屬性CopyLocal設定為false,因為我們在主工程中已經添加了,可以重用)
3). 添加類Division.cs.

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using ContractLibrary;

namespace DynamicExtension
{
    /// <summary>
    /// 乘法運算器
    /// </summary>
    [Export(typeof(IOperate))]
    public class DivisionButton : Button, IOperate
    {
        [Import("DivisionButtonContract", AllowRecomposition = true)]
        public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }

        [Import("DivisionSybomContract", AllowRecomposition = true)]
        public string Symbol { set; get; }

        [Import("ClickHandler")]
        public OperateHandler ClickAction { get; set; }

        #region IOperate 成員

        public double Op(double left, double right)
        {
            return left * right;
        }

        #endregion

        public DivisionButton()
        {
            this.Click += (s, e) => ClickAction(this);
        }
    }
}

 

4).  添加配置類ComponentConfiguration.cs

代碼

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;

namespace DynamicExtension
{
    /// <summary>
    /// 為每個運算器的屬性配置值
    /// </summary>
    public class ComponentConfiguration
    {
        [Export("DivisionButtonContract")]
        public string AddLabel { get { return "Div"; } }
        [Export("DivisionSybomContract")]
        public string AddSymbol { get { return "/"; } }
    }
}

 
5). 修改Home.cs ,為其註冊下載包的相關事件和回調

1.
代碼

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.ComponentModel.Composition;
using ContractLibrary;

namespace MefDemo
{
    public partial class Home : Page
    {
        [ImportMany(typeof(IOperate),AllowRecomposition = true)]
        public ObservableCollection<IOperate> Operates = new ObservableCollection<IOperate>();

        [Export("ClickHandler")]
        public OperateHandler ClickHandler { get { return OperateButton_Click; } }

        private PackageCatalog Catalog;

        /// <summary>
        /// 用於介面控制項響應運算後的一些更新工作
        /// </summary>
        /// <param name="Operate">運算器</param>
        public void OperateButton_Click(IOperate Operate)
        {
            try
            {
                Symbol.Text = Operate.Symbol;
                double left = double.Parse(LeftNum.Text);
                double right = double.Parse(RightNum.Text);
                this.Result.Text = Operate.Op(left, right).ToString();
            }
            catch (Exception e)
            {
                ChildWindow errorWin = new ErrorWindow(e);
                errorWin.Show();
            }
        }

        public Home()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Home_Loaded);
            //註冊按鈕事件
            this.DynamicLoadButton.Click += (s, e) =>
            {
                //下載包
                Package.DownloadPackageAsync(
                    new Uri("DynamicExtension.xap", UriKind.Relative),
                    (args, package) => Catalog.AddPackage(package)
                );
                //包被添加到PackageCatalog後會自動重新組合
                //並對添加了AllowRecomposition = true屬性的Import匯入器重新輸入資料
            };
        }

        void Home_Loaded(object sender, RoutedEventArgs e)
        {
            //組合當前XAP包中所有組件(Parts)
            Catalog = new PackageCatalog();
            Catalog.AddPackage(Package.Current);
            CompositionContainer container = new CompositionContainer(Catalog);
            container.ComposeParts(this);

            //組合後所有實現運算介面(IOperate)的運算器都將被自動填滿到 Operates 集合。
            //將運算器綁定到 ListBox 控制項,用於呈現。
            this.operateList.DataContext = Operates;
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

    }
}

 

Ok,最終介面。
 
點擊DynamicLoadOperate按鈕後
 

    程式中還有很多細節沒有展開說明,理論性的介紹可以參考MSDN和CodePlex上的文檔。

文章出處:飛諾網(www.firnow.com):http://dev.firnow.com/course/4_webprogram/asp.net/netjs/20100714/442928.html

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.