IntentProvide a pattern to simplify dynamic loading, interrogation , and caching of the types contained in an assembly. ProblemThe .NET framework provides a fairly complete set of classes to load and interrogate an assembly. This pattern enhances this functionality to simplify the retrieval of the type information from an assembly. Once loaded, rarely will a type be used only once. This pattern will eliminate the need to return to the assembly each time the type is needed. Finally, when dynamically loading assemblies, the client application will typically be looking for a specific interface in the assembly. Because of this, a method is provided to retrieve only classes that implement a specific interface. ForcesUse the Dynamic Assembly Loader pattern when:
StructureThe Dynamic Assembly Loader (Figure 3.12) consists of one class that does the work of loading and caching assemblies and a client that consumes the types that are loaded. The loader provides three overridden methods for retrieving types from an assembly. The first returns all types from the assembly that implements the specified interface. The second returns all types that implement a specific interface. The third returns a specific type from the assembly. Because the loader will cache what is loaded, the client is assumed to hold a reference to the loader. Figure 3.12. Dynamic Assembly Loader pattern structure.
ConsequencesThe Dynamic Assembly Loader has the following benefits and liabilities:
Participants
ImplementationThis pattern uses .NET's reflection classes to dynamically load and interrogate an assembly. The main class used, the Assembly class, provides the ability to load an assembly from the full path . Once loaded, each of the types is available through a collection. To create an object from a type, though, Reflection must be used to find and call the constructor to use to create an object. Anyone who ever had to use the IDispatch interface in the past will see the similarity in finding and calling the appropriate constructor (or any method). A sample of finding a constructor that takes an integer and string as parameters and calling that constructor is shown below. Listing 3.14 Constructing an object using Reflection.using System.Reflection; // Build the array that defines the // parameter types that would be // passed in to the constructor Type[] types = new Type[2]; types[0] = typeof(int); types[1] = typeof(string); ConstructorInfo constructor = myType.GetConstructor(types); // Build the array of the actual values // to be passed in to the constructor Object[] objects = new Object[2]; objects[0] = 23; objects[1] = "hello world"; object objDynamic = constructor.Invoke(objects); |