Dynamic Loading of Assemblies

The preceding discussion about locating and loading assemblies refers to assemblies that are known at compile time through the application's references. There is an alternative method of locating and loading an assembly that is useful for certain scenarios.

In this technique, the location of the assembly is supplied by the application, using a URL or filename. The normal rules for locating the assembly do not apply — only the location specified by the application is used.

The location is just a string variable, so it may come from a configuration file or a database. In fact, the assembly to be loaded may be newly created, and perhaps did not even exist when the original application was compiled. Because the information to load the assembly can be passed into the application on the fly at run time, this type of assembly loading is called dynamic loading.

The LoadFrom Method of the Assembly Class

The Assembly class has a shared method called LoadFrom that takes a URL or filename and returns a reference to the assembly at that location. Here's a code example of LoadFrom in action, getting an assembly reference from a URL:

Dim asmDynamic As [Assembly]
asmDynamic = [Assembly].LoadFrom("http://www.dotnetmasters.com/DynamicWindows.dll")

As previously discussed, the brackets around Assembly are needed because it is a reserved keyword in Visual Basic. The brackets indicate that the word applies to the Assembly class, and the keyword is not being used.

After these lines are executed, the code contains a reference to the assembly at the given location. That enables the reflection operations discussed earlier for finding types in the assembly. Recall that one such operation is getting a reference to a particular type (which could be a class, a structure, or an enumeration) in the assembly.

For dynamic loading, normally the GetType method of the Assembly class is used to get the reference, using a string that represents the identification of the type. The identification consists of the full namespace path that uniquely identifies the type within the current application. Once a reference to a type is obtained, an instance of the type can be created, even though the assembly was loaded dynamically.

For example, suppose that you wanted to get an instance of a certain form in the assembly, with a namespace path of MyProject.MainWindow. The following line of code would get a reference to the type for that form:

Dim typMyWindow As Type = formAsm.GetType("MyProject.MainWindow")

The type reference can then be used to generate an instance of the type. To do this, you need another class in the System namespace called the Activator class. This class has a shared method called CreateInstance, which takes a type reference and returns an instance of that type. You could, therefore, get an instance of the form with these lines:

Dim window As Object
window = Activator.CreateInstance(typeMyWindow)

CreateInstance always returns a generic object. That means it may be necessary to coerce the returned reference to a particular type to gain access to the type's interface. For example, assuming that you knew the object was actually a WPF window, you could cast the preceding instance into the type of System.Windows.Window and then do normal operations available on that window:

Dim FormToShow As Form = CType(objForm, Window)
FormToShow.MdiParent = Me
FormToShow.Show()

At this point, the form will operate normally. It will behave no differently from a form that was in a referenced assembly.

If the newly loaded form needs to load other classes in the dynamic assembly, nothing special needs to be done. For example, suppose that the form just shown needs to load an instance of another form, named Window2, that resides in the same dynamically loaded assembly. The standard code to instantiate a window will work fine. The CLR will automatically load the Window2 type, because it already has a reference to the assembly containing Window2.

Furthermore, suppose that the dynamically loaded form needs to instantiate a class from another DLL that is not referenced by the application. For example, suppose that the form needs to create an instance of a Customer object, and the Customer class is in a different DLL. As long as that DLL is in the same folder as the dynamically loaded DLL, the CLR will automatically locate and load the second DLL.

Dynamic Loading Example

To see dynamic loading in action, try the following step-by-step example:

1. Create a new WPF Application project in Visual Studio and name it ProVB2012_Ch17. Place a single button on the window, and change its content to Open Window.
2. Double-click the Open Window button to get to its Click event in the Code Editor. Then go to the top of the code module and insert the following Imports statement:
 Imports System.Reflection
3. Insert the code shown in Listing 17-1 into the button's Click event (code file: MainWindow .xaml.vb):
 Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
     Dim sLocation As String = "C:TempProVB2012_DynamicWindows.dll"
     If My.Computer.FileSystem.FileExists(sLocation) Then
         Dim sType As String = "ProVB2012_DynamicWindows.MainWindow"
         Dim DynamicAssembly As [Assembly] = _
                  [Assembly].LoadFrom(sLocation)
         Dim DynamicType As Type = DynamicAssembly.GetType(sType)
         Dim DynamicObject As Object
         DynamicObject = Activator.CreateInstance(DynamicType)
         ' We know it's a form - cast to form type
         Dim WindowToShow As Window = CType(DynamicObject, Window)
         WindowToShow.Show()
     Else
         MsgBox("Unable to load assembly " & sLocation & _
                " because the file does not exist")
     End If
 End Sub
4. Run the program and click the Open Window button. You should get a message box with the message “Unable to load assembly C:TempProVB2012_DynamicWindows.dll because the form does not exist.” Leave this program running while you carry out the next few steps.
5. Start another separate Visual Studio instance, and create a new Windows Forms Application project named ProVB2012_DynamicWindows. On the blank MainWindow that appears, drag over a few controls. It doesn't really matter what controls you drag onto the MainWindow. The version that can be downloaded for the book includes some labels, and text boxes.
6. In the properties for ProVB2012_DynamicWindows, first be certain to uncheck the check box labeled “Enable application framework.” Then change the application type to WPF Class Library.
7. Build the ProVB2012_DynamicWindows project by selecting Build ⇒ Build ProVB2012_DynamicWindows from the Visual Studio menu. This will place a file named ProVB2012_DynamicWindows.dll in the project's inDebug directory (or the inRelease directory if you happen to have the Release configuration set in Visual Studio).
8. Create a directory named C:Temp and copy the ProVB2012_DynamicWindows.dll file to that directory.
9. Return to the running program ProVB2012_DynamicWindows. Click the Load button again. This time, it should load the assembly from the DLL you just copied and launch an instance of Form1 from the ProVB2012_DynamicWindows project.

Notice that the ProVB2012_DynamicWindows.dll was created and compiled after the ProVB2012_Ch17.exe project that loaded it. It is not necessary to recompile or even restart ProVB2012_Ch17.exe to load a new assembly dynamically, as long as ProVB2012_Ch17.exe knows the location of the assembly and the type to be loaded from it.

Putting Assemblies to Work

The previous code examples include hard-coded strings for the location of the assembly and the identification of the type. There are uses for such a technique, such as certain types of Internet deployment of an application. However, when using dynamic loading, it is common for these values to be obtained from outside the code. For example, a database table or an XML-based configuration file can be used to store the information.

This enables you to add new capabilities to a .NET application on the fly. A new assembly with new functionality can be written, and then the location of the assembly and the identity of the type to load from the assembly can be added to the configuration file or database table. Of course this same behavior is completely unacceptable in a fully managed environment such as Windows RT.

Unlike application assemblies automatically located by the CLR, which must be in the application's directory or a subdirectory of it, dynamically loaded assemblies can be anywhere the application knows how to access. Possibilities include the following:

  • A website
  • A directory on the local machine
  • A directory on a shared network machine

The security privileges available to code vary, depending on where the assembly was loaded from. Code loaded from a URL via HTTP has a very restricted set of privileges by default compared to code loaded from a local directory.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset