views:

384

answers:

2

It's a common sense when you are developing a big silverlight application that break it into many small components, to make the original XAP file relatively small and dynamically load the necessary DLLs from the server side on demand.

An easy way is to download(From WebClient) the dll in the program in the runtime accroding to the URL stored in the System.Windows.Application.Current.Host.Source(commonly), use the Assembly object and the reflection mechanism to dynamically parse the IL code and retrive information in the DLLs, to create instance of it and use it. But after this process, this Dll is still invisible for the whole application.

But this way seems to be 'local and temporary', now I am searching a 'global and everlasting' way that can dynamically load the DLLs from the client side, add this Dll to the whole project(just like add reference to this project in the visual studio). After the loading, I hope the application can use the classes or whatever in the newly loaded Dll just like use the ones in the DLLs originally included in the XAP loaded at the very beginning, use them in any threads, although the reflection is still used, I can use this dll in any threads or anywhere or anytime after this loading.

I am asking if this kind of lazy loading, I mean, real loading, can it be implemented in the .NET silverlight, or how can I do this.

It's relatively difficult for me, but maybe rather easy for you.

Thanks a lot in advance.

+1  A: 

I'm not 100% certain this is what you're looking for, but in the Silverlight project properties, check "Reduce XAP size by using application library caching".

This will load any dependent libraries when the XAP loads, but keep them in separate zips. Any library that is built from you must contain a "libraryname.extmap.xml" file. This is the trigger to DevStudio that it should bundle it up as a zip. The properties of the file should have its "Copy to Output Dir" checked. The contents should look like:

<?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"&gt;
  <assembly>
    <name>Common</name>
    <version>1.0.0.0</version>
    <publickeytoken>20f21d15449ebfc7</publickeytoken>
    <relpath>Common.dll</relpath>
    <extension downloadUri="Common.zip" />
  </assembly>
</manifest>
Joel Lucsy
I am not going to reduce the XAP size, actually I want to reduce the size of things which loaded at the beginning, I want to load the dlls in the running of the program, dynamically add these dlls to the application. The size is getting bigger, but bit by bit, I don't want to load anything immediately at the beginning, through the XAP size is relatively small with a lot of library caching.
abusemind
But I do really thank u for your advice, it seems to be useful and helpful. I may change my design.
abusemind
This feature seems to have some bugs in it, as we have seen that the response does not always return the 'cached' libraries in IE 7, 8 FWIW
PortageMonkey
PortageMonkey-Can you give more details? We've run into general code caching issues when quickly iterating our builds during development, but haven't pinned anything down.
Joel Lucsy
Joel -- At this time, we have had to disable assembly caching (through the built in mechanism), as we have not been able to solve the issue in IE. Essentially, a WireShark or Fiddler capture reveals that the 'cached" DLL's are simply not requested, but it is an intermittent problem with no discernible pattern as of yet. Firefox does not seem to have the same issues.
PortageMonkey
+1  A: 

I made it that way , make a singleton class as an assemblyLibrary create a webservice , which takes an identifier of th app you want to launch and gives you the a collection of Url´s for the dll´s, check if you already have them in your library, if not download and refernce them , here are a few keyparts:

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


   }
Ren Hoek