Silverlight应用程序中动态延迟加载DLL的高级主题

时间:2009-11-26 06:39:45

标签: c# .net silverlight reflection lazy-loading

当您开发一个大型的Silverlight应用程序,将其分解为许多小组件,使原始XAP文件相对较小并根据需要从服务器端动态加载必要的DLL时,这是常识。

一种简单的方法是从运行时的程序中下载(从WebClient)程序中的dll到存储在System.Windows.Application.Current.Host.Source(通常)中的URL,使用Assembly对象和反射动态解析IL代码并检索DLL中的信息,创建它的实例并使用它的机制。但是在这个过程之后,这个Dll对于整个应用程序仍然是不可见的。

但这种方式似乎是“本地的和临时的”,现在我正在寻找一种可以从客户端动态加载DLL的'全局和永久'方式,将这个Dll添加到整个项目中(就像添加引用一样)这个项目在视觉工作室)。在加载之后,我希望应用程序可以使用新加载的Dll中的类或任何内容,就像使用最初加载的XAP中最初包含的DLL中的那些,在任何线程中使用它们,尽管仍然使用反射,我可以在任何线程中或在此加载后的任何地方或任何时间使用此DLL。

我在问这种延迟加载,我的意思是,实际加载,是否可以在.NET silverlight中实现,或者我该怎么做呢。

这对我来说相对困难,但对你来说可能相当容易。

提前多多感谢。

2 个答案:

答案 0 :(得分:1)

我不是100%肯定这是您正在寻找的,但在Silverlight项目属性中,选中“使用应用程序库缓存减少XAP大小”。

这将在XAP加载时加载任何依赖库,但将它们保存在单独的zip中。从您构建的任何库都必须包含“libraryname.extmap.xml”文件。这是DevStudio的触发器,它应该将其捆绑为zip。文件的属性应选中“复制到输出目录”。内容应如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <assembly>
    <name>Common</name>
    <version>1.0.0.0</version>
    <publickeytoken>20f21d15449ebfc7</publickeytoken>
    <relpath>Common.dll</relpath>
    <extension downloadUri="Common.zip" />
  </assembly>
</manifest>

答案 1 :(得分:1)

我这样做,将一个单独的类作为assemblyLibrary 创建一个webservice,它获取你想要启动的应用程序的标识符,并为你提供dll的Url集合, 检查你的库中是否已经有它们,如果没有下载并参考它们,这里有几个关键部分:

       public static void LoadRefeferenceAssembly(string AssemblyCollectionName)
   {
       AssemblyDefinitionProviderClient alc = new AssemblyDefinitionProviderClient();

       alc.getAssemblyListCompleted += alc_getAssemblyListCompleted;
       alc.getAssemblyListAsync(AssemblyCollectionName);

   }

   static void alc_getAssemblyListCompleted(object sender, getAssemblyListCompletedEventArgs e)
   {
       if (e.Result == null || e.Error != null)
       {
           throw new ArgumentException("Assembly for cache error");
       }
       foreach (AssemblyDescription description in e.Result)
       {
           if (ReferencedAssemblies.Keys.Contains(description.name)) continue;
           var ass = new ReferencedAssembly { Name = description.name, PercentLoaded = 0.0, Uri = new Uri(description.url, description.kind), State = ReferencedAssemblyStates.None };
           if (description.isMainAssembly)
           {
               _currentMainAssembly = description.name;
               ass.MainUIElementName = description.MainUIElementString;
           }
           ReferencedAssemblies.Add(description.name,ass);
       }
       beginCaching();
   }

   private static void beginCaching()
   {
       var tocache = Instance._ReferencedAssemblies.Values.FirstOrDefault(re => re.State == ReferencedAssemblyStates.None);
       if (tocache == null)
       {
           changeContent();
           return;
       }
       var wc = new WebClient();
       //progress here
       wc.OpenReadCompleted += (sender, e) =>
                                   {
                                       if (e.Result != null || e.Error == null)
                                       {
                                           AssemblyPart apart = new AssemblyPart();
                                           tocache.AssemblyPart = apart.Load(e.Result);
                                           tocache.State = ReferencedAssemblyStates.Done;
                                           setStatus(tocache.Name + "Loaded");
                                       }
                                       else
                                       {
                                           tocache.Error = e.Error;
                                           tocache.State = ReferencedAssemblyStates.Error;
                                           setStatus(tocache.Name + "Error by Loading");
                                       }
                                       beginCaching();
                                   };
       wc.OpenReadAsync(tocache.Uri);


   }