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 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 runtime, this type of assembly loading is called dynamic loading.

The Assembly Class

References to assemblies, and operations to be performed on assemblies in code, are mostly contained in a .NET Framework class called the Assembly class. It is part of the System.Reflection namespace. In the code examples that follow, assume that the following Imports statement is at the top of the code module:

 Imports System.Reflection

The Assembly class has a shared method called LoadFrom, which 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/loancalc2.dll") 

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 other operations on the assembly to take place. One such operation is getting a reference to a particular type (which could be a class, structure, or enumeration) in the assembly. The reference to a type is needed to instantiate the type when an assembly is loaded dynamically. 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.

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

 Dim typMyForm As Type = formAsm.GetType("MyProject.Form1")

The type reference can then be used to generate an instance of the type. To do this you need another class in System.Reflection called the Activator class. This class has a shared method called CreateInstance, which takes a type reference and returns an instance of that type. (If you are familiar with Active Server Pages and older versions of Visual Basic, CreateInstance is functionally similar to the CreateObject function in those environments.) You could, therefore, get an instance of the form with these lines:

  Dim objForm As Object objForm = Activator.CreateInstance(typeMyForm) 

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 Windows Form, you could coerce the preceding instance into the type of System.Windows.Forms.Form and then do normal operations that are available on a form:

  Dim FormToShow As Form = CType(objForm, System.Windows.Forms.Form) 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 (except for potential code access security limitations, as discussed in Chapter 12).

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 Form2, that resides in the same dynamically loaded assembly. The standard code to instantiate a form will work fine. The CLR will automatically load the Form2 type because it already has a reference to the assembly containing Form2.

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, do the following step-by-step example:

  1. Open a new Windows Application in Visual Studio. Name it DynamicLoading. On the blank Form1 that appears, drag a Button from the Toolbox, and set its Text property to Load.

  2. Double-click the Load 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 following code into the button’s Click event:

      Dim sLocation As String = "C:\Deploy\DynamicForms.dll" If My.Computer.FileSystem.FileExists(sLocation) Then     Dim sType As String = "DynamicForms.Form1"     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 FormToShow As Form = CType(DynamicObject, Form)     FormToShow.Show() Else     MsgBox("Unable to load assembly " & sLocation & _            " because the file does not exist") End If 

  4. Run the program and click the Load button. You should get a message box with the message “Unable to load assembly C:\Deploy\DynamicForms.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 Application project named DynamicForms. On the blank Form1 that appears, drag over a few controls. It doesn’t really matter what controls you drag onto Form1. The version that can be downloaded for the book includes some labels, buttons, and text boxes.

  6. In the properties for DynamicForms, change the Application type. In the drop-down for Application type, select Class Library.

  7. Build the DynamicForms project by selecting Build image from bookimage from book Build DynamicForms from the Visual Studio menu. This will place a file named DynamicForms.dll in the project’s \bin\Debug directory (or the \bin\Release directory if you happen to have the Release configuration set in Visual Studio).

  8. Create a directory named C:\Deploy and copy the DynamicForms.dll file to that directory.

  9. Return to the running program DynamicLoading. 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 DynamicForms project.

Notice that the DynamicForms.dll was created and compiled after the DynamicLoading.exe project that loaded it. It is not necessary to recompile or even restart DynamicLoading.exe to load a new assembly dynamically, as long as DynamicLoading.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 an 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.

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 get to. 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, as shown earlier, has a very restricted set of privileges by default compared to code loaded from a local directory. Chapter 12 has details on code access security, default security policies, and how default policies can be changed.




Professional VB 2005 with. NET 3. 0
Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
ISBN: 0470124709
EAN: 2147483647
Year: 2004
Pages: 267

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net