cannot instantiate an instance of the type。 The following is the singleton code for ConfigurationLoader (placed in the Definitions assembly)。 Public Class ConfigurationLoader Public Shared ReadOnly Property Instance() As ConfigurationLoader Get Return ConfigurationLoader。_instance End Get End Property Private Sub New() _availableTypes = New Dictionary(Of String; ConfigurationInfo)() End Sub Private Shared _instance As ConfigurationLoader Shared Sub New() _instance = New ConfigurationLoader() End Sub 。 。 。 The singleton property Instance is declared as Shared; allowing a reference of ConfigurationLoader。Instance。 The implementation of the shared property must reference a shared data member; which is the data member _instance in this example。 The data member _instance is instantiated by the shared constructor Shared New()。 The instance constructor will instantiate the Dictionary _availableTypes。 ■Note The shared constructor is called before the instance constructor and therefore before any client code has a chance to access members of the class。 Using the Instantiated Type Now that we’ve covered the singleton aspect; we need to get back to the original problem of writing the code to instantiate a type dynamically。 The following code is used to instantiate Impl1 in the Main() method of CallRuntimeImplementation’s principal module。 …………………………………………………………Page 348…………………………………………………………… 326 CH AP T E R 1 2 ■ L E A R N I N G A B OU T A PP L I CA TI O N CO N F I G U R AT IO N AN D D Y N A M I C L O AD I N G ConfigurationLoader。Instance。Load() Dim definition as IDefinition = _ ConfigurationLoader。Instance。Instantiate(Of IDefinition)(〃Impl1〃) Console。WriteLine(definition。TranslateWord(〃hello〃)) ■Note You might get errors running the code。 If you do; it is because the assemblies are not in the same path and the dynamic loading methods cannot find the assemblies。 Solve this by copying all of the assemblies into a single directory and running the code。 The first line is used to retrieve the assembly and type information from the configuration file。 The second line is used to instantiate Impl1 and then cast Implementations1。 Implementation to type IDefinition。 The cast will work because the IDefinition interface has been implemented by Implementations1。Implementation。 The assigned variable definition will reference a valid object instance that implements IDefinition and the method TranslateWord()。 At this point; we need to step back and reflect on what has occurred。 We have defined within a configuration file the location of a type。 Some source code in the application read the configuration file at runtime and stored the available types。 The calling code knew about only the abstract type made available under the label Impl1 and knew it implemented the interface IDefinition。 Then; using some magic involving dynamic techniques; the type’s assembly is loaded and instantiated。 This process is unique because an administrator has the ability to update where and what type should be instantiated and called; without needing to repile or update the infrastructure。 That flexibility makes it much simpler for you to update function ality without having to update the caller of the functionality。 ■Note The ability to dynamically update the functionality is of benefit to the administrator of the application。 There is minimal benefit to the developer; because the developer has already converted the architecture to use ponents。 In general; developers consider this approach to ponents as building a plug…in architecture。 Enhancing the Configuration File The configuration file is a bit of a clumsy definition because all of the available types are stored in a single key/value pair。 It would be preferable to be able to define custom items in the configuration file; as follows: This approach is preferable because it is easier to read and understand; thus reducing the chances that you will have an error。 Additionally; because the various identifiers are broken up; you don’t need to build a lengthy single…line string。 …………………………………………………………Page 349…………………………………………………………… CH AP T E R 1 2 ■ L E AR N IN G AB O U T AP P L I CAT I ON CO N F IG U R AT IO N A N D D Y N A M IC L O AD IN G 327 ■Note For simplicity; we will have only a single dynamic type; represented by the XML element。 In a plete solution; you would use the same approach with different interfaces and types。 If you were to add the sample XML into the configuration file and run the application; you would get a configuration initialization failure。 That’s because the XML node is not a standard configuration item and thus needs custom parsing。 And when you want custom parsing; you need to tell the configuration infrastructure what code to execute。 The following is the plete configuration file with custom processing tags。