轉帖|其它|編輯:郝浩|2011-03-07 13:45:17.000|閱讀 785 次
概述:眾所周知,在Silverlight 2開始每個項目編譯后都會打包成為一個xap文件,如果我們要訪問當前xap文件中的UserControl比較容易,那我們如何訪問一個外部xap文件中的內容呢?甚至于如何訪問一個互聯(lián)網(wǎng)上的xap文件呢?本文將簡單介紹一下在Silverlight中如何訪問外部xap文件。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
眾所周知,在Silverlight 2開始每個項目編譯后都會打包成為一個xap文件,如果我們要訪問當前xap文件中的UserControl比較容易,那我們如何訪問一個外部xap文件中的內容呢?甚至于如何訪問一個互聯(lián)網(wǎng)上的xap文件呢?
本文將簡單介紹一下在Silverlight中如何訪問外部xap文件。
需求
現(xiàn)在我們先來看一下需求,大致是這樣子的,在服務端我們有兩個xap文件,其中MainProject.xap文件將會在MainProjectTestPage.aspx中引用,而ExternalProject.xap文件中的UserControl將會在MainProject.xap文件中訪問,并進行顯示,如下圖所示:
現(xiàn)在我們來建立相關的項目,最終完成的項目結構如下圖所示:
這樣在編譯后,將會在ClientBin文件夾下產(chǎn)生兩個.xap文件,現(xiàn)在我們將在MainProject.xap文件中訪問ExternalProject.xap中的UserControl。
分析
在實現(xiàn)這個過程中,我們將會遇到兩個問題:
1.因為沒有任何頁面引用ExternalProject.xap文件,所以它不會下載到客戶端,這一點我們可以通過編碼的方式來下載它。
2.訪問ExternalProject.xap中的UserControl,我們需要找到對應的程序集,以便使用反射,我們知道在xap文件是一個標準的zip文件,它會包含相關的程序集(接下來我會寫一篇文章專門解釋xap文件),如下圖所示:
現(xiàn)在解決了xap文件的下載已經(jīng)程序集的訪問問題,我們可以著手來實現(xiàn)了。
實現(xiàn)
實現(xiàn)的過程也是相當簡單,首先我們使用WebClient去下載xap文件,相信大家都知道該怎么做了,如下代碼所示
void myButton_Click(object sender, RoutedEventArgs e)
{
Uri address = new Uri( "//localhost:4161/ClientBin/ExternalProject.xap");
WebClient webClient = new WebClient();
webClient.OpenReadCompleted +=
new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(address);
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
// 得到下載結果
}
這一步比較簡單,接下來我們將根據(jù)下載的結果,得到相應的程序集。我們知道在xap文件中的AppManifest.xaml文件相當于一個清單,列出了當前xap文件用到的程序集(下篇文章將會介紹),它的內容如下所示:
<Deployment xmlns="//schemas.microsoft.com/client/2007/deployment"
xmlns:x="//schemas.microsoft.com/winfx/2006/xaml"
EntryPointAssembly= "ExternalProject"
EntryPointType= "ExternalProject.App"
RuntimeVersion= "2.0.30523.6">
<Deployment.Parts>
<AssemblyPart x:Name="ExternalProject" Source="ExternalProject.dll" />
</Deployment.Parts>
</Deployment>
注意,在Deployment.Parts節(jié)點下包含了當前應用程序中所有的程序集。首先要根據(jù)下載的結果獲取AppManifest.xaml文件中的內容,如下代碼所示:
Stream stream = Application.GetResourceStream(
new StreamResourceInfo(packageStream, null),
new Uri( "AppManifest.xaml", UriKind.Relative)).Stream;
String appManifestString = new StreamReader(stream).ReadToEnd();
有了AppManifest.xaml中內容,就可以根據(jù)它來構造一個Deployment對象,Deployment對象提供了當前應用程序的Part和本地化信息清單,它的定義如下所示:
注意它定義了一個很重要的屬性Parts,通過該屬性我們就可以訪問所有Deployment中的程序集。好了,現(xiàn)在我們看如何通過AppManifest.xaml中的內容構造Deployment對象,以及遍歷其中的程序集,如下代碼所示:
Deployment deployment = (Deployment)XamlReader.Load(appManifestString);
Assembly assembly = null;
foreach (AssemblyPart assemblyPart in deployment.Parts)
{
if (assemblyPart.Source == assemblyName)
{
String source = assemblyPart.Source;
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(packageStream,
"application/binary"),
new Uri(source,UriKind.Relative));
assembly = assemblyPart.Load(streamInfo.Stream);
break;
}
}
return assembly;
注意,在遍歷時如果我們找到程序集名等于我們想要訪問的程序集,則直接返回該程序集。最終完整的LoadAssemblyFromXap方法代碼如下:
Assembly LoadAssemblyFromXap(Stream packageStream,String assemblyName)
{
Stream stream = Application.GetResourceStream(
new StreamResourceInfo(packageStream, null),
new Uri( "AppManifest.xaml", UriKind.Relative)).Stream;
String appManifestString = new StreamReader(stream).ReadToEnd();
Deployment deployment = (Deployment)XamlReader.Load(appManifestString);
Assembly assembly = null;
foreach (AssemblyPart assemblyPart in deployment.Parts)
{
if (assemblyPart.Source == assemblyName)
{
String source = assemblyPart.Source;
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(packageStream,
"application/binary"),
new Uri(source,UriKind.Relative));
assembly = assemblyPart.Load(streamInfo.Stream);
break;
}
}
return assembly;
}
得到程序集后,再使用反射創(chuàng)建相關的實例,并在頁面上加載,如下代碼所示:
Assembly assembly = LoadAssemblyFromXap(e.Result, "ExternalProject.dll");
UIElement element = assembly.CreateInstance("ExternalProject.SubPage") as UIElement;
this.holder.Children.Add(element);
運行后效果如下圖所示:
跨域訪問
在上面的示例中,不涉及到跨域(我會專門寫一篇文章介紹)調用的問題,如果大家想訪問的xap文件與當前xap文件不在同一站點中,需要添加跨域訪問文件,如下代碼所示:
clientaccesspolicy.xml:
<<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*" />
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
總結
本文介紹了在Silverlight中如何訪問外部xap文件這一技巧,希望對大家有所幫助。
本站文章除注明轉載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網(wǎng)絡轉載