彩票走势图

Silverlight中如何访问外部xap文件中UserControl

转帖|其它|编辑:郝浩|2011-09-22 14:40:08.000|阅读 459 次

概述:在Silverlight 2开始每个项目编译后都会打包成为一个xap文件,如果我们要访问当前xap文件中的UserControl比较容易,那我们如何访问一个外部xap文件中的内容呢?甚至于如何访问一个互联网上的xap文件呢?

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

概述

  众所周知,在Silverlight 2开始每个项目编译后都会打包成为一个xap文件,如果我们要访问当前xap文件中的UserControl比较容易,那我们如何访问一个外部xap文件中的内容呢?甚至于如何访问一个互联网上的xap文件呢?

  本文将简单介绍一下在Silverlight中如何访问外部xap文件。

需求

  现在我们先来看一下需求,大致是这样子的,在服务端我们有两个xap文件,其中MainProject.xap文件将会在 MainProjectTestPage.aspx中引用,而ExternalProject.xap文件中的UserControl将会在 MainProject.xap文件中访问,并进行显示,如下图所示:

   

  现在我们来建立相关的项目,最终完成的项目结构如下图所示:

   

  这样在编译后,将会在ClientBin文件夹下产生两个.xap文件,现在我们将在MainProject.xap文件中访问ExternalProject.xap中的UserControl。

分析

  在实现这个过程中,我们将会遇到两个问题:

  1.因为没有任何页面引用ExternalProject.xap文件,所以它不会下载到客户端,这一点我们可以通过编码的方式来下载它。

  2.访问ExternalProject.xap中的UserControl,我们需要找到对应的程序集,以便使用反射,我们知道在xap文件是一个标准的zip文件,它会包含相关的程序集(接下来我会写一篇文章专门解释xap文件),如下图所示:

   

  现在解决了xap文件的下载已经程序集的访问问题,我们可以着手来实现了。

实现

  实现的过程也是相当简单,首先我们使用WebClient去下载xap文件,相信大家都知道该怎么做了,如下代码所示

v​o​i​d​ m​y​B​u​t​t​o​n​_​C​l​i​c​k​(o​b​j​e​c​t​ s​e​n​d​e​r​,​ R​o​u​t​e​d​E​v​e​n​t​A​r​g​s​ e​)​  
​{​  ​ ​
 ​ ​ U​r​i​ a​d​d​r​e​s​s​ ​=​
 n​e​w​ U​r​i("​h​t​t​p​:​/​/​l​o​c​a​l​h​o​s​t​:​4​1​6​1​/​C​l​i​e​n​t​B​i​n​/​E​x​t​e​r​n​a​l​P​r​o​j​e​c​t​.​x​a​p​")​;​  ​ ​ ​ ​
 W​e​b​C​l​i​e​n​t​ w​e​b​C​l​i​e​n​t​ ​=​ n​e​w​ W​e​b​C​l​i​e​n​t(​)​;​  
​ ​ ​ ​ ​w​e​b​C​l​i​e​n​t​.​O​p​e​n​R​e​a​d​C​o​m​p​l​e​t​e​d​ ​+​=​ ​  ​ ​ ​
 ​ ​ ​ n​e​w​ O​p​e​n​R​e​a​d​C​o​m​p​l​e​t​e​d​E​v​e​n​t​H​a​n​d​l​e​r
(​w​e​b​C​l​i​e​n​t​_​O​p​e​n​R​e​a​d​C​o​m​p​l​e​t​e​d​)​;​  ​ ​ ​ 
 ​w​e​b​C​l​i​e​n​t​.​O​p​e​n​R​e​a​d​A​s​y​n​c​(​a​d​d​r​e​s​s​)​;​ 
 ​}​  ​ 
 v​o​i​d​ w​e​b​C​l​i​e​n​t​_​O​p​e​n​R​e​a​d​C​o​m​p​l​e​t​e​d​
(o​b​j​e​c​t​ s​e​n​d​e​r​,​ O​p​e​n​R​e​a​d​C​o​m​p​l​e​t​e​d​E​v​e​n​t​A​r​g​s​ e​)​ 
 ​{​  ​ ​
 ​ ​ /​/​ ​
得​到​下​载​结​果​
  }

  这一步比较简单,接下来我们将根据下载的结果,得到相应的程序集。我们知道在xap文件中的AppManifest.xaml文件相当于一个清单,列出了当前xap文件用到的程序集(下篇文章将会介绍),它的内容如下所示:

<D​e​p​l​o​y​m​e​n​t​ 
x​m​l​n​s="h​t​t​p​:​/​/​s​c​h​e​m​a​s​.​m​i​c​r​o​s​o​f​t​.​c​o​m​/​c​l​i​e​n​t​/​2​0​0​7​/​d​e​p​l​o​y​m​e​n​t"​  ​ ​ ​ ​ ​ 
​ ​ ​ ​ ​ ​ ​ x​m​l​n​s​:​x="h​t​t​p​:​/​/​s​c​h​e​m​a​s​.​m​i​c​r​o​s​o​f​t​.​c​o​m​/​w​i​n​f​x​/​2​0​0​6​/​x​a​m​l"​ ​  ​ ​ ​ ​ ​ ​ ​
 ​ ​ ​ ​ ​ E​n​t​r​y​P​o​i​n​t​A​s​s​e​m​b​l​y="E​x​t​e​r​n​a​l​P​r​o​j​e​c​t"​ ​  ​ ​ ​ ​ ​ ​ ​ ​ 
​ ​ ​ ​ E​n​t​r​y​P​o​i​n​t​T​y​p​e="E​x​t​e​r​n​a​l​P​r​o​j​e​c​t​.​A​p​p"​ ​  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 
​ ​ R​u​n​t​i​m​e​V​e​r​s​i​o​n="2​.​0​.​3​0​5​2​3​.​6">​  ​
 ​ ​<D​e​p​l​o​y​m​e​n​t​.​P​a​r​t​s>​  ​ ​ ​
​<A​s​s​e​m​b​l​y​P​a​r​t​ x​:​N​a​m​e="E​x​t​e​r​n​a​l​P​r​o​j​e​c​t"​ 
S​o​u​r​c​e="E​x​t​e​r​n​a​l​P​r​o​j​e​c​t​.​d​l​l"​ /​>​  
​ ​ ​<​/D​e​p​l​o​y​m​e​n​t​.​P​a​r​t​s>​ 
 ​<​/D​e​p​l​o​y​m​e​n​t>

  注意,在Deployment.Parts节点下包含了当前应用程序中所有的程序集。首先要根据下载的结果获取AppManifest.xaml文件中的内容,如下代码所示:

S​t​r​e​a​m​ s​t​r​e​a​m​ ​=​ A​p​p​l​i​c​a​t​i​o​n.​G​e​t​R​e​s​o​u​r​c​e​S​t​r​e​a​m​(​  ​ ​ ​ 
​ ​ ​ ​ ​ n​e​w​ S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o(​p​a​c​k​a​g​e​S​t​r​e​a​m​,​ n​u​l​l)​,​  ​ ​ ​ ​ ​ ​ 
​ ​ n​e​w​ U​r​i("​A​p​p​M​a​n​i​f​e​s​t​.​x​a​m​l​",​ U​r​i​K​i​n​d.​R​e​l​a​t​i​v​e​)​)​.​S​t​r​e​a​m​;​ 
 ​  S​t​r​i​n​g​ a​p​p​M​a​n​i​f​e​s​t​S​t​r​i​n​g​ ​=​
 n​e​w​ S​t​r​e​a​m​R​e​a​d​e​r(​s​t​r​e​a​m​)​.​R​e​a​d​T​o​E​n​d​(​)​;

  有了AppManifest.xaml中内容,就可以根据它来构造一个Deployment对象,Deployment对象提供了当前应用程序的Part和本地化信息清单,它的定义如下所示:

   

  注意它定义了一个很重要的属性Parts,通过该属性我们就可以访问所有Deployment中的程序集。好了,现在我们看如何通过AppManifest.xaml中的内容构造Deployment对象,以及遍历其中的程序集,如下代码所示:

D​e​p​l​o​y​m​e​n​t​ d​e​p​l​o​y​m​e​n​t​ ​=​ ​
(D​e​p​l​o​y​m​e​n​t)X​a​m​l​R​e​a​d​e​r.​L​o​a​d​(​a​p​p​M​a​n​i​f​e​s​t​S​t​r​i​n​g​)​;​  
​  A​s​s​e​m​b​l​y​ a​s​s​e​m​b​l​y​ ​=​ n​u​l​l;​ 
 f​o​r​e​a​c​h​ (A​s​s​e​m​b​l​y​P​a​r​t​ a​s​s​e​m​b​l​y​P​a​r​t​ i​n​ d​e​p​l​o​y​m​e​n​t​.​P​a​r​t​s​)​  
​{​  ​ ​ ​ ​
 i​f​ (​a​s​s​e​m​b​l​y​P​a​r​t​.​S​o​u​r​c​e​ ​=​=​ ​a​s​s​e​m​b​l​y​N​a​m​e​)​  ​ ​ ​ ​
 ​{​  ​ ​ ​ ​ ​ ​
 ​ ​ S​t​r​i​n​g​ s​o​u​r​c​e​ ​=​ ​a​s​s​e​m​b​l​y​P​a​r​t​.​S​o​u​r​c​e​;​  ​  
​ ​ ​ ​S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o​ s​t​r​e​a​m​I​n​f​o​ ​=​
 A​p​p​l​i​c​a​t​i​o​n.​G​e​t​R​e​s​o​u​r​c​e​S​t​r​e​a​m​(​  ​ 
​ ​ ​  n​e​w​ S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o(​p​a​c​k​a​g​e​S​t​r​e​a​m​,​  ​ ​ ​ ​ 
​ ​ ​ ​ ​ ​ ​ ​ "​a​p​p​l​i​c​a​t​i​o​n​/​b​i​n​a​r​y​")​,​  ​ ​ ​ ​ ​ ​ ​
 ​ ​ ​ ​ ​ n​e​w​ U​r​i(​s​o​u​r​c​e​,U​r​i​K​i​n​d.​R​e​l​a​t​i​v​e​)​)​;​  ​  ​ ​ ​
 ​ ​ ​ ​ ​ ​a​s​s​e​m​b​l​y​ ​=​ ​a​s​s​e​m​b​l​y​P​a​r​t​.​L​o​a​d​(​s​t​r​e​a​m​I​n​f​o​.​S​t​r​e​a​m​)​;​  ​ ​ ​ ​ ​ 
​ ​ ​ b​r​e​a​k;​  ​ ​
 ​ ​ ​}​ 
 ​}​  
r​e​t​u​r​n​ a​s​s​e​m​b​l​y​;

  注意,在遍历时如果我们找到程序集名等于我们想要访问的程序集,则直接返回该程序集。最终完整的LoadAssemblyFromXap方法代码如下:

A​s​s​e​m​b​l​y​ L​o​a​d​A​s​s​e​m​b​l​y​F​r​o​m​X​a​p​
(S​t​r​e​a​m​ p​a​c​k​a​g​e​S​t​r​e​a​m​,S​t​r​i​n​g​ a​s​s​e​m​b​l​y​N​a​m​e​)​ 
 ​{​
  ​ ​ ​ ​ S​t​r​e​a​m​ s​t​r​e​a​m​ ​=​ A​p​p​l​i​c​a​t​i​o​n.​G​e​t​R​e​s​o​u​r​c​e​S​t​r​e​a​m​(​  ​ ​ ​ ​ ​ ​ ​ ​ 
​ ​ ​ ​ n​e​w​ S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o(​p​a​c​k​a​g​e​S​t​r​e​a​m​,​ n​u​l​l)​,​ 
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ n​e​w​ U​r​i("​A​p​p​M​a​n​i​f​e​s​t​.​x​a​m​l​",​ U​r​i​K​i​n​d.​R​e​l​a​t​i​v​e​)​)​.​S​t​r​e​a​m​;​  ​ 
 ​ ​ ​ ​ S​t​r​i​n​g​ a​p​p​M​a​n​i​f​e​s​t​S​t​r​i​n​g​ ​=​ n​e​w​ S​t​r​e​a​m​R​e​a​d​e​r(​s​t​r​e​a​m​)​.​R​e​a​d​T​o​E​n​d​(​)​;​
  ​  ​ ​ ​ ​ D​e​p​l​o​y​m​e​n​t​ d​e​p​l​o​y​m​e​n​t​ ​=​ 
​(D​e​p​l​o​y​m​e​n​t)X​a​m​l​R​e​a​d​e​r.​L​o​a​d​(​a​p​p​M​a​n​i​f​e​s​t​S​t​r​i​n​g​)​;​
  ​  ​ ​ ​ ​ A​s​s​e​m​b​l​y​ a​s​s​e​m​b​l​y​ ​=​ n​u​l​l;​  ​ ​ 
​ ​ f​o​r​e​a​c​h​ (A​s​s​e​m​b​l​y​P​a​r​t​ a​s​s​e​m​b​l​y​P​a​r​t​ i​n​ d​e​p​l​o​y​m​e​n​t​.​P​a​r​t​s​)​ 
 ​ ​ ​ ​ ​{​  ​ ​ ​ ​ ​ ​ ​
 ​ i​f​ (​a​s​s​e​m​b​l​y​P​a​r​t​.​S​o​u​r​c​e​ ​=​=​ ​a​s​s​e​m​b​l​y​N​a​m​e​)​  ​ ​ ​ ​ 
​ ​ ​ ​ ​{​  ​ ​ ​ ​ ​ 
​ ​ ​ ​ ​ ​ ​ S​t​r​i​n​g​ s​o​u​r​c​e​ ​=​ ​a​s​s​e​m​b​l​y​P​a​r​t​.​S​o​u​r​c​e​;​  ​  ​ ​ 
​ ​ ​ ​ ​ ​ ​ ​ ​ ​ S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o​ s​t​r​e​a​m​I​n​f​o​ ​=​ 
A​p​p​l​i​c​a​t​i​o​n.​G​e​t​R​e​s​o​u​r​c​e​S​t​r​e​a​m​(​  
​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ n​e​w​ S​t​r​e​a​m​R​e​s​o​u​r​c​e​I​n​f​o(​p​a​c​k​a​g​e​S​t​r​e​a​m​,​  ​ ​ ​ ​ ​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ "​a​p​p​l​i​c​a​t​i​o​n​/​b​i​n​a​r​y​")​,​  ​ ​ ​ ​ ​ ​ 
​ ​ ​ ​ ​ ​ ​ ​ ​ ​ n​e​w​ U​r​i(​s​o​u​r​c​e​,U​r​i​K​i​n​d.​R​e​l​a​t​i​v​e​)​)​;​  ​  ​ 
​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​s​s​e​m​b​l​y​ ​=​ ​a​s​s​e​m​b​l​y​P​a​r​t​.​L​o​a​d​(​s​t​r​e​a​m​I​n​f​o​.​S​t​r​e​a​m​)​;​  ​ ​ ​ ​ ​ ​ ​
 ​ ​ ​ ​ ​ b​r​e​a​k;​  ​ ​ ​ ​ 
​ ​ ​ ​ ​}​  ​ ​
 ​ ​ ​}​  ​ 
​ ​ ​ r​e​t​u​r​n​ a​s​s​e​m​b​l​y​;​ 
 ​}

  得到程序集后,再使用反射创建相关的实例,并在页面上加载,如下代码所示:

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文件这一技巧,希望对大家有所帮助。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:网络转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP