Расширенная тема динамической отложенной загрузки библиотек DLL в приложении silverlight - PullRequest
1 голос
/ 26 ноября 2009

Когда вы разрабатываете большое приложение Silverlight, которое разбивает его на множество мелких компонентов, это здравый смысл, чтобы сделать исходный файл XAP относительно небольшим и динамически загружать необходимые библиотеки DLL со стороны сервера по требованию.

Простым способом является загрузка (из WebClient) библиотеки DLL в программе во время выполнения в соответствии с URL-адресом, хранящимся в System.Windows.Application.Current.Host.Source (обычно), использование объекта Assembly и отражения механизм динамического разбора кода IL и извлечения информации в DLL, создания его экземпляра и использования. Но после этого процесса этот Dll все еще невидим для всего приложения.

Но этот путь кажется «локальным и временным», теперь я ищу «глобальный и вечный» способ, который может динамически загружать библиотеки DLL со стороны клиента, добавить этот Dll ко всему проекту (как добавить ссылку на этот проект в визуальной студии). Я надеюсь, что после загрузки приложение сможет использовать классы или что-то еще во вновь загруженном Dll, точно так же, как использовать те в DLL, которые изначально были включены в XAP, загруженный в самом начале, использовать их в любых потоках, хотя отражение все еще используется Я могу использовать эту DLL в любых потоках или в любом месте или в любое время после этой загрузки.

Я спрашиваю, может ли такая ленивая загрузка, я имею в виду, реальная загрузка, быть реализована в .NET silverlight или как я могу это сделать.

Это относительно сложно для меня, но, может быть, довольно легко для вас.

Заранее большое спасибо.

Ответы [ 2 ]

1 голос
/ 26 ноября 2009

Я сделал это таким образом, сделаю одноэлементный класс в качестве сборочной библиотеки создайте веб-сервис, который берет идентификатор приложения, которое вы хотите запустить, и предоставляет вам коллекцию URL-адресов для DLL, проверьте, есть ли у вас их в вашей библиотеке, если не скачать и ссылаться на них, вот несколько ключей:

       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);


   }
1 голос
/ 26 ноября 2009

Я не уверен на 100%, что это то, что вам нужно, но в свойствах проекта Silverlight установите флажок «Уменьшить размер XAP с помощью кэширования библиотеки приложений».

При загрузке XAP будут загружены все зависимые библиотеки, но они будут храниться в отдельных архивах. Любая библиотека, созданная из вас, должна содержать файл "libraryname.extmap.xml". Это триггер к DevStudio, который должен связать его как почтовый индекс. В свойствах файла должен быть установлен флажок «Copy to Output Dir». Содержимое должно выглядеть так:

<?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>
...