Silverlight開發廋身攻略(二)

作者: 劉其武  來源: 博客園  發布時間: 2010-12-20 22:48  閱讀: 1230 次  推薦: 0   原文鏈接   [收藏]  

  繼上一篇《Silverlight開發廋身攻略(一)》,在上一節中我主要介紹了在實際開發中怎么動態加載圖片資源的方法,并附有實例。在這一節中主要給大家介紹MEF(Managed Extensibility Framework)的知識來實現Xap包的動態加載。

  Managed Extensibility Framework(MEF)是.NET平臺下的一個擴展性管理框架,它是一系列特性的集合,包括依賴注入(DI)以及Duck Typing等。MEF為開發人員提供了一個工具,讓我們可以輕松的對應用程序進行擴展并且對已有的代碼產生最小的影響,開發人員在開發過程中根據功能要求定義一些擴展點,之后擴展人員就可以使用這些擴展點與應用程序交互;同時MEF讓應用程序與擴展程序之間不產生直接的依賴,這樣也允許在多個具有同樣的擴展需求之間共享擴展程序。簡單的說:MEF程序設計主要Export (輸出)、Import (輸入)、Compose (組合)三個動作來完成。MEF的核心包括一個catalog和一個CompositionContainer。category用于發現擴展,而container用于協調創建和梳理依賴性。每個可組合的Part提供了一個或多個Export,并且通常依賴于一個或多個外部提供的服務或Import。每個Part管理一個實例為應用程序運行。
  關于MEF的基礎知識在這里不是重點,大家可以在網上搜一下,有很多介紹這方面的文章。下面直截以實例轉入正題。在實例中我們創建三個Silverlight Application項目,它們分別是:MEFLoadXap、FristXap、SecondXap。MEFLoadXap是主項目,它是一個容器,通過它來動態加載FristXap、SecondXap包。本實例環境是VS.net 2010 net4.0,在Net4.0中集成了MEF的功能。

  一、新建MEFLoadXap項目

      1、用VS.net 2010新建名為MEFLoadXap的Silverlight Application項目,添加System.ComponentModel.Composition、System.ComponentModel.Composition.Initialization引用,如下圖所示:    

  2、在MEFLoadXap項目下添加DeploymentCatalogService.cs文件,在文件中添加IDeploymentCatalogService接口,并編寫繼承此接口的DeploymentCatalogService的類,此類主要封裝了下載指定Xap包,自動導入帶有Export屬性標簽類型為UserControl控件對象。

  IDeploymentCatalogService代碼:

 
/// <summary>
/// 加載Xap服務接口
/// </summary>
public interface IDeploymentCatalogService
{

/// <summary>
/// 加載Xap包的方法
/// </summary>
/// <param name="uri">Xap包路徑</param>
/// <param name="completedAction">加載完成后的事件</param>
void AddXap(string uri, Action<AsyncCompletedEventArgs> completedAction = null);
/// <summary>
/// 移除Xap包的方法
/// </summary>
/// <param name="uri">Xap包路徑</param>
void RemoveXap(string uri);
}

  DeploymentCatalogService類的代碼:

 
/// <summary>
/// 加載Xap服務類
/// </summary>
[Export(typeof(IDeploymentCatalogService))]
public class DeploymentCatalogService : IDeploymentCatalogService
{

private static AggregateCatalog _aggregateCatalog;
Dictionary
<string, DeploymentCatalog> _catalogs;

public DeploymentCatalogService()
{
_catalogs
= new Dictionary<string, DeploymentCatalog>();
}

/// <summary>
/// 初始化對象的靜態方法
/// </summary>


public static void Initialize()
{
_aggregateCatalog
= new AggregateCatalog();
_aggregateCatalog.Catalogs.Add(
new DeploymentCatalog());
CompositionHost.Initialize(_aggregateCatalog);
}

/// <summary>
/// 加載Xap包的方法
/// </summary>
/// <param name="uri">Xap包路徑</param>
/// <param name="completedAction">加載完成后的事件</param>

public void AddXap(string uri, Action<AsyncCompletedEventArgs> completedAction = null)
{
DeploymentCatalog catalog;

if (!_catalogs.TryGetValue(uri, out catalog))
{
catalog
= new DeploymentCatalog(uri);

if (completedAction != null)
{
catalog.DownloadCompleted
+= (s, e) => completedAction(e);
}

else
{
catalog.DownloadCompleted
+= catalog_DownloadCompleted;
}

catalog.DownloadAsync();
_catalogs[uri]
= catalog;
_aggregateCatalog.Catalogs.Add(catalog);
}
}


void catalog_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{

if (e.Error != null)
{

throw e.Error;
}
}

/// <summary>
/// 移除Xap包的方法
/// </summary>
/// <param name="uri">Xap包路徑</param>

public void RemoveXap(string uri)
{
DeploymentCatalog catalog;

if (_catalogs.TryGetValue(uri, out catalog))
{
_aggregateCatalog.Catalogs.Remove(catalog);
_catalogs.Remove(uri);
}
}
}
3、修改設計MainPage,在MainPage界面設計中我們把整個界面分為左、右兩部分,左邊放兩個按鈕,右邊放一個容器控件用于承載顯示動態下載Xap包中的控件,其Xaml代碼如下:
 
<Grid x:Name="LayoutRoot" Background="#FFD8D8D8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Height="36" Width="160" Margin="20,106,20,158" Content="加載一" Click="Button_Click"></Button>
<Button Height="36" Width="160" Margin="20,189,20,75" Content="加載二" Click="Button_Click_1"></Button>
<Border x:Name="parentContent" Grid.Column="1"></Border>
</Grid>
 

  MainPage類的CS代碼:

 
public partial class MainPage : UserControl, IPartImportsSatisfiedNotification
{

public MainPage()
{
InitializeComponent();

//通過此方法調用DeploymentCatalogService對象
//自動將此對象與CatalogService屬性邦定在一起
CompositionInitializer.SatisfyImports(this);
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}


void MainPage_Loaded(object sender, RoutedEventArgs e)
{
LoadSelectedModule();
}

private string m_xapName = "FristXap.xap";

#region IPartImportsSatisfiedNotification Members

public void OnImportsSatisfied()
{
LoadSelectedModule();
}


#endregion
/// <summary>
/// 導入類型是IDeploymentCatalogService并帶有Export屬性標簽對象
/// </summary>
[Import]
public IDeploymentCatalogService CatalogService { get; set; }
/// <summary>
/// 導入類型是UserContronl并帶有Export屬性標簽的所有控件
/// </summary>
[ImportMany(AllowRecomposition = true)]
public Lazy<UserControl>[] mefModules { get; set; }


/// <summary>
/// 加載XAP包的方法
/// </summary>
private void LoadSelectedModule()
{

string selectXapName = m_xapName.Replace(".xap", ".");

CatalogService.AddXap(m_xapName);
var ctrs
= (from m in mefModules.ToList()
where m.Value.ToString().Contains(selectXapName)
select m).FirstOrDefault();

if (ctrs != null)
{
parentContent.Child
= ctrs.Value;
}

}


private void Button_Click(object sender, RoutedEventArgs e)
{
m_xapName
= "FristXap.xap";
LoadSelectedModule();
}


private void Button_Click_1(object sender, RoutedEventArgs e)
{
m_xapName
= "SecondXap.xap";
LoadSelectedModule();
}
}

  二、新建FristXap項目

  1、用VS.net 2010新建名為FristXap的Silverlight Application項目,添加System.ComponentModel.Composition、System.ComponentModel.Composition.Initialization引用

  2、刪除FristXap項目下的App.xaml、MainPage.xaml文件,因它是被加載項目基本沒有什么用處

  3、添加名為Ellipse.xaml用戶控件,此控件主要作用是畫一個橢圓。此控件效果圖如下:    

    控件Xaml代碼如下:

 
<Grid x:Name="LayoutRoot" >
<Ellipse Height="300" Width="400" Fill="#FF3BC73B"></Ellipse>
<TextBlock Text="第一個XAP包中的橢圓控件" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14"></TextBlock>
</Grid>

  三、新建SecondXap項目

  1、用VS.net 2010新建名為SecondXap的Silverlight Application項目,添加System.ComponentModel.Composition、System.ComponentModel.Composition.Initialization引用

  2、刪除SecondXap項目下的App.xaml、MainPage.xaml文件 

  3、添加名為Rectangle.xaml用戶控件,此控件主要作用是畫一個矩形。此控件效果圖如下:    

  四、編譯運行項目,點擊如下圖所示的按鈕動態加載FristXap.xap、SecondXap.xap包中的控件對象,加載過程是首先判斷指定的包是否已下載到本地,如果在本地則直接加載;如果不在本地,則先到遠程服務器上下載Xap包,后加載控件對象。運行效果圖如下:   

  本實例源代碼:下載

0
0
 
標簽:Silverlight
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()