【问题标题】:silverlight 4, dynamically loading xap modulessilverlight 4,动态加载 xap 模块
【发布时间】:2010-09-09 04:08:25
【问题描述】:

我知道可以使用 Prism 或 MEF 框架动态加载 xap 模块。但是,我不想使用这些框架;而是手动加载我的 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 的 UserControl,所以我想实例化该类。在当前项目(Main.xap)中,我添加了对 Sales.xap 项目的引用,但是,因为我手动加载它,所以我设置了“Copy Local = False”。但是在执行的时候,下面的代码会抛出TypeLoadException:

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

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

【问题讨论】:

  • 除了 .NET 4 之外,更简单的方法是使用 Silverlight 4 中内置的托管扩展框架 (MEF)。

标签: silverlight assembly-resolution xap


【解决方案1】:

这是基于提问者在下面的自我回答,而不是问题。

如果您删除一个项目/模块,输出 DLLs/XAP 文件确实会挂起。如果您单击“显示所有文件”按钮,您将在 clientbinbinobj 文件夹中看到这些剩余的输出文件相关项目。

您可以从项目中单独删除它们,或者,如有疑问,搜索所有 BIN 和 OBJ(例如使用桌面资源管理器)并删除所有这些文件夹。 BIN/CLIENTBIN/OBJ 文件夹将在需要时重新创建(这是 Visual Studio 中的“干净”选项应该完成的工作!)

希望这会有所帮助。

【讨论】:

  • 我选择了正确的答案,但是,我注意到 Visual Studio 的 Build->Clean 菜单没有帮助。删除 bin/obj 文件夹可能会有所帮助(我还没有这样做),我只是不想重复这样做。所以,目前我正在做的是更改 Web 服务器的端口号。顺便说一句,这个问题经常发生,即使我什么都没重命名。
【解决方案2】:

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

【讨论】:

  • 我遇到了同样的问题,我使用的是 chrome - @Xds 是对的。问题似乎与 chrome 缓存 xap 文件有关!如果您为相同的 URL 打开一个隐身窗口,您将看到最新的更改(因为隐身不缓存)。此外,如果您将 IExplorer 用于相同的 url,它将显示最新的 - 它也不会缓存。人们希望谷歌浏览器不会如此严格地缓存 xap。 :(
【解决方案3】:

在执行新编译的 Silverlight 时,为了避免此类问题,我所做的是清除浏览器缓存,chrome 甚至有一个清除的 silverlight 缓存;)

【讨论】:

    【解决方案4】:

    这种 XAP Cache 现象通常是由于 Visual Studio 嵌入式 Web 服务器(ASP.NET 开发服务器)造成的。 只要停止此服务器的出现,缓存就会被清除。 重新启动您的项目,并调用最新版本的 xap。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      相关资源
      最近更新 更多