Page view counter
Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0 Subscribe to this thread
Last post 12-04-2008 9:44 AM by Jargon64. 9 replies.
Sort Posts:
04-26-2008 1:20 PM
Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0

This is what I want to do:

I want to dynamically load a class from an extenal assembly into my application. (using Silverlight 2.0 and Visual Studio 2008).

The class which I want to load is called MyAssembly.MyClass; It is derived from Canvas; It resides in an assembly called MyAssembly.dll. I amually deployed the DLL in the ClientBin directory of my Web-Project.

Her is what have tried:

I have tried to load the assembly using Assembly.Load("MyAssembly"). It failed with File not found. (Are there any good working examples for 'Assembly.Load()'?).

Now I am trying to solve the problem with AssemblyPart.Load(...). I am able to load the assembly, but nw I am not able to create instances of objects within that assembly. Can you help?

Here is the code I am working on:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Reflection;
using System.Net;
using System.IO;

namespace POC_Reflection_Dynamic_Load
{
   public partial class Page : Canvas
  
{
     
TextBlock txt;
     
WebClient downloader;

     
public Page()
      {
        
// Initialize Debug Test Area
        
txt = new TextBlock();
         txt.Text =
"";
         txt.FontSize = 12;
         txt.Foreground =
new SolidColorBrush(Color.FromArgb(255, 255, 0, 200));
        
this.Children.Add(txt);

        
// Download the DLL using a WebClient?
       
downloader = new WebClient();
        downloader.OpenReadCompleted +=
new OpenReadCompletedEventHandler(onOpenReadCompleted);
        downloader.OpenReadAsync(
new Uri("MyAssembly.dll", UriKind.Relative));
        debug(
"Downloader Base Address = " + downloader.BaseAddress.ToString());
      }

     
private void onOpenReadCompleted(object o, OpenReadCompletedEventArgs args)
      {
        
loadAssembly(args.Result);
      }

     
private void loadAssembly(Stream s)
      {
          Assembly a;

         
try
         
{
              
AssemblyPart ap = new AssemblyPart();
               ap.Load(s);
               debug(
"Assembly Part successfully loaded: " + ap.Source);

              
// Here is the problem. Loading the Assembly (DLL) into the AssemblyPart was successful.
              
// But how do I create an instance of a class which is defined in that DLL? Here is an
              
// attempt do do that.
              
//(IT DOES NOT WORK !!!)
              
Canvas can = (Canvas)Assembly.GetExecutingAssembly().CreateInstance("MyAssembly.MyClass");
              
if (can == null)
               {
                     debug(
"can is null!!!!!!!!!");
                    
return;
               }

              debug(
"Canvas successfully created");
             
this.Children.Add(can);

            
debug("Canvas successfully added");
          }
         
catch (Exception ex)  
          {
             debug(
"Exception when loading the assembly part:");
             debug(ex.ToString());
          }
      }

      
public void debug(String s)
      {
         txt.Text +=
"\n" + s;
      }
   }
}

 

 

BlueAquarius

Loading...
Joined on 04-24-2008
Posts 37
04-26-2008 3:27 PM
Marked as Answer
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0

I found the solution. I hope this helps other people....

When loading the DLL as a Stream into the AssemblyPart, you can create an Assembly at the same time:

          AssemblyPart ap = new AssemblyPart();
         
Assembly a = ap.Load(s);

The Assembly will then allow you to create an object:

          Canvas can = (Canvas)a.CreateInstance("MyAssembly.MyClass");

Here is the entire method loadAssembly(). All other parts of the source code (above) remain unchanged.
 

  

 

private void loadAssembly(Stream s)
{
    
try
    
{
         
AssemblyPart ap = new AssemblyPart();
         
Assembly a = ap.Load(s);
         
Canvas can = (Canvas)a.CreateInstance("MyAssembly.MyClass");
         
if (can == null)
          {
                 debug(
"can is null!!!!!!!!!");
                
return;
          }

         
this.Children.Add(can);
          debug(
"Canvas successfully added");
     }
    
catch (Exception ex)
     {
          debug(
"Exception when loading the assembly part:");
          debug(ex.ToString());
     }
}

 

 

 

BlueAquarius

Loading...
Joined on 04-24-2008
Posts 37
05-11-2008 3:22 PM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0

Thank you for this. Your code works great. I made an adaption using my resizable window control. I placed it here:

SilverlightDesktop.net

With source code of course and even a credit for you.


SilverlightDesktop.net

A framework that allows you to dynamically load Silverlight modules into resizable draggable windows.

adefwebserver

Loading...
Joined on 06-07-2003
Los Angeles, CA
Posts 99
05-13-2008 6:14 AM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlight 2.0

Well, thanks for your comment. And thanks for putting it up. It is always good to know that someone finds this usefull

BlueAquarius

Loading...
Joined on 04-24-2008
Posts 37
07-29-2008 1:41 PM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0

 Thank you for this, I had tried to follow the instructions of the MSDN page (See Here) but it wasn't working.

quentez

Loading...
Joined on 01-18-2006
Posts 1
11-15-2008 4:44 PM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlioght 2.0

 I followed your advice but loading seems not to work if one uses application ressources ? My load fails on  this line

        <TextBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2" x:Name="AdditionalPersonDescription" Canvas.ZIndex="9" AcceptsReturn="true" Width="100" Height="50" HorizontalAlignment="Left" VerticalAlignment="Top" Style="{StaticResource TextBoxDescription}" KeyDown="AdditionalPersonDescription_KeyDown" Visibility="Collapsed" d:IsHidden="True"/>
 

with error "TextBoxDescription" not found, TextBoxDescription is in App.xaml of the control to load NOT on the loader (of course).

 So this looks to me as even byndmaically loaded componets try to look up ressources in  the PARENT application not the loaded dll. I would say this is a bug or ?

 

 

Joe Robe

joer00

Loading...
Joined on 07-05-2006
Posts 113
11-15-2008 7:26 PM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlioght 2.0

joer00:

 I followed your advice but loading seems not to work if one uses application ressources ?

You can either put the resources in the control that is being dynamically loaded or pass the resources to the control through it's ".Tag" property.


SilverlightDesktop.net

A framework that allows you to dynamically load Silverlight modules into resizable draggable windows.

adefwebserver

Loading...
Joined on 06-07-2003
Los Angeles, CA
Posts 99
12-04-2008 7:48 AM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlioght 2.0

This thread explains exactly what I need to do. Looking at SilverlightDesktop.net makes me realise how similar my project is... but I just can't get it working.

I can get the WebClient object to retrieve the assembly and feed the stream into an AssemblyPart object's Load method. The assembly is loaded correctly and stored in the Assembly object and I can even create an instance of the class I need (checked that it is not null with the debugger), but when I try to assign the Content property of a TabItem with the created instance (which is actually a subclass of UserControl), it just comes up blank and not the test text that is actually in the UserControl. No errors, nothing. It's like the UserControl loses everything it contains. Here's what I'm currently working with.

WebClient handler:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    // Debug information
    ((TabItem)tabs.SelectedItem).Content = String.Format("{0} - {1} - {2}", (e.Error == null), e.Error, e.Result);
    // Create new AssemblyPart object and load assembly into a new Assembly object
    AssemblyPart ap = new AssemblyPart();
    Assembly a = ap.Load(e.Result);
    // Create instance of ProjectsModule and set as currently selected TabItem's Content
    ((TabItem)tabs.SelectedItem).Content = a.CreateInstance("Project.Modules.ProjectsModule") as UserControl;
}

ProjectsModule.xaml

<UserControl x:Class="Project.Modules.ProjectsModule"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock>Test String</TextBlock>
    </Grid>
</UserControl>

ProjectsModule.xaml.cs

namespace Project.Modules
{
    public partial class ProjectsModule : UserControl
    {
        public ProjectsModule()
        {
            InitializeComponent();
        }
    }
}

Hopefully one of you guys can see someone obvious that I'm doing wrong ;) I can't understand why I'm just getting blank content even when the debugger shows a ProjectsModule object being created from the CreateInstance method.

Thanks in advance!

 

Jargon64

Loading...
Joined on 08-28-2008
Posts 7
12-04-2008 9:10 AM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlioght 2.0

You may need to just call the UpdateLayout method on the containing control to fix this.

Also SilverlightDesktop.net adds a control to a window control then adds the window control to the main canvas, so 3 things are happening:

 

SilverlightWindowControl objSilverlightWindowControl = new SilverlightWindowControl(objSilverlightDesktopModule.WindowSize);
objSilverlightWindowControl.Window.Content = objUserControl;
objSilverlightWindowControl.WindowName.Text = objSilverlightDesktopModule.ModuleName;
Canvas.SetLeft(objSilverlightWindowControl, (double)intWindowLocationLeft);
Canvas.SetTop(objSilverlightWindowControl, (double)intWindowLocationTop);

this.LayoutRoot.Children.Add(objSilverlightWindowControl);
 


SilverlightDesktop.net

A framework that allows you to dynamically load Silverlight modules into resizable draggable windows.

adefwebserver

Loading...
Joined on 06-07-2003
Los Angeles, CA
Posts 99
12-04-2008 9:44 AM
Re: Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverlioght 2.0

UpdateLayout does nothing :(

 I've had a little play and tried to add the content to a new TabItem then add that TabItem to the TabControl with the following code:

 

void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    // Debug information
    ((TabItem)tabs.SelectedItem).Content = String.Format("{0} - {1} - {2}", (e.Error == null), e.Error, e.Result);
    // Create new AssemblyPart object and load assembly into a new Assembly object
    AssemblyPart ap = new AssemblyPart();
    Assembly a = ap.Load(e.Result);
    // Create instance of ProjectsModule and set as currently selected TabItem's Content
    //((TabItem)tabs.SelectedItem).Content = 
    TabItem tab = new TabItem();
    Random random = new Random();
    tab.Header = String.Format("Tab{0}", random.Next(100));
    tab.Content = a.CreateInstance("Project.Modules.ProjectsModule") as UserControl;
    tabs.Items.Add(tab);
}
 The new tab appears correctly with the "Tab#" header, but when I navigate to it, it's blank.  It would appear that the UserControl IS dropping/ignoring all its content and I have no idea why.  Any ideas?, I'm all out :/
Jargon64

Loading...
Joined on 08-28-2008
Posts 7
Microsoft Communities