Skip to main content

Microsoft Silverlight

Answered Question Dynamically load Assemblies ... Assembly.Load() ... AssemblyPart.Load() ... Silverloght 2.0RSS Feed

(0)

BlueAquarius
BlueAqua...

Member

Member

57 points

37 Posts

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

Member

Member

57 points

37 Posts

Answered Question

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

 

 

 

adefwebserver
adefwebs...

Member

Member

448 points

127 Posts

Silverlight MVP

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.

BlueAquarius
BlueAqua...

Member

Member

57 points

37 Posts

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

quentez
quentez

Member

Member

2 points

1 Posts

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.

joer00
joer00

Member

Member

145 points

113 Posts

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

adefwebserver
adefwebs...

Member

Member

448 points

127 Posts

Silverlight MVP

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.

Jargon64
Jargon64

Member

Member

4 points

7 Posts

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!

 

adefwebserver
adefwebs...

Member

Member

448 points

127 Posts

Silverlight MVP

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

Jargon64
Jargon64

Member

Member

4 points

7 Posts

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 :/

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities