Prism On Demand模块加载是否在OOB场景中工作?

时间:2010-05-20 15:15:33

标签: silverlight prism ondemand silverlight-oob

OnDemand Prism模块的加载是否适用于OOB场景?如果是这样,我似乎无法使其发挥作用。一切都在浏览器中没有任何问题。具体来说我: 在代码中注册我的模块:

    protected override IModuleCatalog GetModuleCatalog() {
        var catalog = new ModuleCatalog();
        Uri source;

        if( Application.Current.IsRunningOutOfBrowser ) {
            source = IsolatedStorageSettings.ApplicationSettings[SOURCEURI] as Uri;
        }
        else {
            var src = Application.Current.Host.Source.ToString();
            src = src.Substring( 0, src.LastIndexOf( '/' ) + 1 );
            source = new Uri( src );
            IsolatedStorageSettings.ApplicationSettings[SOURCEURI] = source;
            IsolatedStorageSettings.ApplicationSettings.Save();
        }

        if( source != null ) {
            var mod2 = new ModuleInfo { InitializationMode = InitializationMode.OnDemand,
                          ModuleName = ModuleNames.mod2,
                          ModuleType = "mod2.Module, mod2.Directory, '1.0.0.0', Culture=neutral, PublicKeyToken=null" ),
                          Ref = ( new Uri( source, "mod2.xap" )).AbsoluteUri };

            catalog.AddModule( mod2 );
        }

// per Jeremy Likeness - did not help.
        Application.Current.RootVisual = new Grid();

        return ( catalog );
    }

以后请求加载模块:

mModuleManager.LoadModule( ModuleNames.mod2 );

并等待对该加载模块初始化期间发布的事件的响应。

模块似乎永远不会被加载,当应用程序在调试器下运行时,会出现一个消息框,指出Web服务器返回了“未找到”错误。我可以获取模块的请求URL并将其输入Firefox并下载模块没有问题。

我无法找到任何对此实际可行的参考,但似乎应该如此。我在这个主题上找到的最多的是blog entry by Jeremy Likeness,它涵盖了MEF中的加载模块,但是在这里应用他的知识并没有帮助。

服务器是localhost(我听说它提到这可能会导致问题)。服务器有一个clientaccesspolicy.xml文件 - 虽然我不希望这是必需的。 我正在使用客户端堆栈并在应用程序构建期间注册它:

WebRequest.RegisterPrefix( Current.Host.Source.GetComponents( UriComponents.SchemeAndServer, UriFormat.UriEscaped ), WebRequestCreator.ClientHttp );

后续问题:

是否可以通过某种方式将所有xaps安装到客户端桌面 - 或者只安装主应用程序xap?以某种方式在appmanifest.xml中指定它们吗?

如果只安装了application.xap并且必须下载其他的xaps,是否值得这样做?

2 个答案:

答案 0 :(得分:1)

我曾经在类似的情况下工作过。诀窍是将模块存储在隔离存储中,并使用模块加载器在脱机工作时从独立存储中读取。

这是因为否则,您无法下载与Shell不同的.xap文件中的模块。

谢谢, 达米安

答案 1 :(得分:0)

如果您愿意调整Prism源并自行构建,可以将自定义模块加载器挂接到Prism中。我实际上能够很容易地使用它 - 在我们的应用程序中,我首先在磁盘上查找模块,如果找不到,我会回退到通过支持的第三方商业HTTP堆栈从服务器加载它客户证书。

为此,请下载Prism源代码,然后找到Microsoft.Practices.Composite.Modularity.XapModuleTypeLoader类。该类使用另一个Prism类Microsoft.Practices.Composite.Modularity.FileDownloader来下载.xap内容;但它直接实例化,让你没有机会注入自己的或其他什么。

所以 - 在XapModuleTypeLoader中,我添加了一个静态属性来设置下载器的类型:

public static Type DownloaderType { get; set; }

然后我修改了CreateDownloader()方法以使用上面指定的类型而不是默认类型:

protected virtual IFileDownloader CreateDownloader() {
    if (_downloader == null) { 
        if (DownloaderType == null) {
            _downloader = new FileDownloader();
        } else { 
            _downloader = (IFileDownloader)Activator.CreateInstance(DownloaderType);
        }
    }

    return _downloader;
}

当我的应用启动时,我将属性设置为我自己的下载器类型:

XapModuleTypeLoader.DownloaderType = typeof(LocalFileDownloader);

Voila - 现在Prism会调用您的代码加载其模块。

我可以发送我的LocalFileDownloader类以及它回退的类,如果你感兴趣的话,从网上加载.xap ...我怀疑如果你看看Prism的FileDownloader类,你会看到这很简单。

关于您的其他问题,如果安装了应用程序的URL与您正在讨论的URL相同,或者您处于高级信任状态,则可能不需要clientaccesspolicy.xml文件。

.xaps肯定可以预先安装在客户端上,但它有点工作。我们所做的是编写一个启动器应用程序,它是一个独立的.NET 2.0桌面应用程序。它下载主.xap加上某些模块*(仅在需要时检查更新和下载),然后在必要时卸载/重新安装应用程序,然后启动应用程序。最后两个是通过sllauncher.exe完成的,它是作为Silverlight的一部分安装的。这是一个很好的介绍:http://timheuer.com/blog/archive/2010/03/25/using-sllauncher-for-silent-install-silverlight-application.aspx

假设您在高级信任下运行,还应该可以从SL客户端中预取模块.xaps,但是在用户操作之前实际请求它们之前。您只需将它们放在My Documents下的某个文件夹中,然后使用上述自定义模块加载方法将它们从那里拉出来。

*在我们的例子中,我们的主.xap是应用程序的2/3。我们的.xaps的其余部分很小,所以我们即时下载它们,除了我们创建的一些.xaps作为第三方组件的容器。我们不希望经常更新它们,因此我们预先安装它们。