2010-09-09 102 views
6

我知道有可能动态地装入使用Prism或MEF框架XAP模块。但是,我不想使用这些框架;而是手动加载我的xap文件。所以,我创建了以下课程(改编自互联网):Silverlight 4中,动态加载XAP模块

public class XapLoader 
{ 
    public event XapLoadedEventHandler Completed; 

    private string _xapName; 

    public XapLoader(string xapName) 
    { 
     if (string.IsNullOrWhiteSpace(xapName)) 
      throw new ArgumentException("Invalid module name!"); 
     else 
      _xapName = xapName; 
    } 

    public void Begin() 
    { 
     Uri uri = new Uri(_xapName, UriKind.Relative); 
     if (uri != null) 
     { 
      WebClient wc = new WebClient(); 
      wc.OpenReadCompleted += onXapLoadingResponse; 
      wc.OpenReadAsync(uri); 
     } 
    } 

    private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e) 
    { 
     if ((e.Error == null) && (e.Cancelled == false)) 
      initXap(e.Result); 

     if (Completed != null) 
     { 
      XapLoadedEventArgs args = new XapLoadedEventArgs(); 
      args.Error = e.Error; 
      args.Cancelled = e.Cancelled; 
      Completed(this, args); 
     } 
    } 

    private void initXap(Stream stream) 
    { 
     string appManifest = new StreamReader(Application.GetResourceStream(
     new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml", 
             UriKind.Relative)).Stream).ReadToEnd(); 

     XElement deploy = XDocument.Parse(appManifest).Root; 

     List<XElement> parts = (from assemblyParts in deploy.Elements().Elements() 
           select assemblyParts).ToList(); 

     foreach (XElement xe in parts) 
     { 
      string source = xe.Attribute("Source").Value; 
      AssemblyPart asmPart = new AssemblyPart(); 
      StreamResourceInfo streamInfo = Application.GetResourceStream(
       new StreamResourceInfo(stream, "application/binary"), 
       new Uri(source, UriKind.Relative)); 
      asmPart.Load(streamInfo.Stream); 
     } 
    } 
} 

public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e); 

public class XapLoadedEventArgs : EventArgs 
{ 
    public Exception Error { get; set; } 

    public bool Cancelled { get; set; } 
} 

上面的代码工作正常;我可以加载任何XAP方式如下:

XapLoader xapLoader = new XapLoader("Sales.xap"); 
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed); 
xapLoader.Begin(); 

现在,我有一个在Sales.xap项目叫InvoiceView用户控件,所以我想将类实例。在当前项目(Main.xap)中,我添加了对Sales.xap项目的引用,但是,由于我手动加载,所以我设置了“Copy Local = False”。但是执行时,下面的代码会抛出TypeLoadException:

Sales.InvoiceView view = new Sales.InvoiceView(); 

看来代码找不到InvoiceView类。但是我检查了XapLoader的initXap()方法已成功执行。那么为什么代码无法找到InvoiceView类?有人可以帮我解决这个问题吗?

+0

执行此操作的更简单方法是使用内置于Silverlight 4中的托管扩展性框架(MEF),以及.NET 4. – 2010-10-22 16:14:08

回答

1

这是基于对提问者的下方自我的答案,而不是问题。

如果你删除一个项目/模块输出的DLL/XAP文件不流连。如果您点击“显示所有文件”按钮,您将在相关项目的文件夹中看到clientbin,binobj中的一些剩余输出文件。

alt text

您可以从项目,或有疑问时,搜索所有BIN和OBJ(例如使用桌面浏览器),并删除所有这些文件夹中删除工作。该BIN /的ClientBin /需要(这个作业在Visual Studio中的“干净”的选项应该做的!)

希望这有助于在OBJ文件夹将被重新创建。

+0

我选择你的答案是正确的,但是,我注意到Visual Studio的Build-> Clean菜单没有帮助。删除bin/obj文件夹可能有帮助(我还没有做),我只是不想做因此,目前我所做的是更改Web服务器的端口号,顺便说一下,即使我没有更名,这个问题也经常发生。 – synergetic 2010-09-15 03:59:36

1

好吧,我找到了原因。上面的代码有效。创建一个新的Silverlight项目(Sales.xap)后,我偶然编译了我的解决方案。然后,我删除了Sales.xap中的App类,并将默认的MainPage类重命名为SalesView。然而,不管我多少次编译我的解决方案,Visual Studio的开发Web服务器都加载了第一版的Sales.xap(从?),所以我的代码找不到SalesView。在我的主机Asp.Net项目中,我将开发服务器的端口设置为不同的端口号,问题消失了。所以问题出在Visual Studio的开发服务器上。显然,它将编译的xap文件保存在某个临时文件夹中,并且在源代码更改时并不总是更新这些xap文件。

+0

我遇到了同样的问题,我正在使用chrome - @Xds是正确的。这些问题似乎与铬缓存xap文件大的时间!如果您为同一个网址打开隐身窗口,则会看到最新的更改(因为隐身不会缓存)。另外,如果您使用IExplorer获取相同的网址,它将显示最新消息 - 它也不会缓存。人们会希望谷歌浏览器不会如此严格地缓存xap。 :( – DeeStackOverflow 2010-12-03 18:12:26

0

我做什么当执行新编译的Silverlight是明确的,以避免此类问题的浏览器缓存,铬甚至有一个明确的Silverlight缓存;)

0

这个XAP缓存的现象往往是由于在Visual Studio嵌入式Web服务器( ASP.NET开发服务器)。 只需停止此服务器的发生,缓存将被清除。 重新开始您的项目并调用您的xap的最新版本。