按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
as described in the next section。
■Note For the examples in this chapter; use the XML shown in the listings。 XML is not difficult to learn; but
for now; you’ll get by with what I show you here。 For more information about XML; visit the MSDN XML Developer
Center at http://msdn2。microsoft。/en…us/xml/default。aspx。
Reading a Configuration File
Reading a configuration file is very simple because the Framework es with an easy
to…use configuration API。 For example; to read the value for the key Assemblies; use the following
code; which would be added to your application when the application first starts; such as in the
Main() method of a console program。
Dim value As String = _
System。Configuration。ConfigurationManager。AppSettings(〃Assemblies〃)
…………………………………………………………Page 344……………………………………………………………
322 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
ConfigurationManager is a shared class that provides the entry point to reading items from
a configuration file。
In this example; a couple assumptions have been made。 The first assumption is that you
want to read the configuration settings from the application that is currently executing。 The
second assumption is that you want to read the configuration items stored within the XML
node 。 Based on those two assumptions; the settings are stored in a shared prop
erty named AppSettings; which returns an instance of type NameValueCollection。 (The way that
AppSettings is referenced makes it appear as if AppSettings were an indexer; which it is not。)
When retrieving the buffer of ma…separated identifiers using ConfigurationManager;
you need to parse the buffer and then make sense of the information; as described in the next
section。
Dynamically Loading an Assembly
In terms; to use the configuration file with a dynamically loaded application; you need to
load the assembly; and from the assembly; instantiate the type。 You can reference assemblies
locally and also reference them from the GAC。
Dynamically Instantiating a Type
The code to dynamically instantiate a type requires parsing the ma…separated buffer into
its respective identifiers。 To keep things organized; the three pieces of information are stored
in a class。 This can be called a data class because it has only data members。
The data class is a placeholder; needed only by the code used to dynamically load the type。
This makes it possible to define the data class as a private class; because a private class implies
only the parent class can instantiate it。
With the ConfigurationLoader class defined as the class used to dynamically instantiate
other types; the private class is declared as follows (added to the Definitions project):
Public Class ConfigurationLoader
Private _availableTypes As Dictionary(Of String; ConfigurationInfo) = _
New Dictionary(Of String; ConfigurationInfo)
Private Class ConfigurationInfo
Public AssemblyName As String
Public EasyName As String
Public TypeName As String
End Class
End Class
ConfigurationInfo contains three data members: AssemblyName; EasyName; and TypeName。
The class is prefixed with Private; indicating that nothing external to the ConfigurationLoader
class can see the configuration。 Had ConfigurationInfo been declared with the Public keyword;
the following code would have been legal。
Dim cls As ConfigurationLoader。ConfigurationInfo = _
New ConfigurationLoader。ConfigurationInfo()
…………………………………………………………Page 345……………………………………………………………
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 323
ConfigurationInfo is used to store the information from the configuration file。 The config
uration information is cross…referenced using a Dictionary; where the key is the EasyName data
member。
To parse the configuration information and create the individual instances of
ConfigurationInfo; the following code (part of ConfigurationLoader) is used。
Imports System。Configuration
Public Sub Load()
Dim value As String = ConfigurationManager。AppSettings(〃assemblies〃)
Dim values As String() = value。Split(〃;〃c)
Dim c1 As Integer = 0
Do While (c1 《 values。Length)
Dim configInfo As New ConfigurationInfo()
configInfo。EasyName = values(c1)
configInfo。TypeName = values((c1 + 1))
configInfo。AssemblyName = values((c1 + 2))
_availableTypes。Add(values(c1); configInfo)
c1 = (c1 + 3)
Loop
End Sub
The configuration is read using AppSettings; and then split into an array of string element
values。 Processing three array elements at a time iterates the array。 With every iteration; an
instance of ConfigurationInfo is created。 Once the buffer has been processed; it is possible
to dynamically instantiate a type using the following ConfigurationLoader method。
Imports System。Reflection
。 。 。
Public Function Instantiate(Of RequestedType)(ByVal identifier As String) _
As RequestedType
If Not _availableTypes。ContainsKey(identifier) Then
Throw New ArgumentException((〃identifier (〃 & identifier & _
〃) is not a listed type〃))
End If
Dim info As ConfigurationInfo = _availableTypes。Item(identifier)
Dim assemblyName As AssemblyName = _
AssemblyName。GetAssemblyName(info。AssemblyName)
Console。WriteLine((〃assemblyname(〃 & assemblyName。ToString() & 〃)〃))
Return DirectCast( _
Assembly。Load(assemblyName)。CreateInstance(info。TypeName); _
RequestedType)
End Function
Look at the declaration of the method Instantiate(); and you will see that it is a
generics method (discussed in Chapter 11)。 The idea is to instantiate a type and perform an
automatic cast to the request type。 It avoids needing to define Instantiate() using the Object
…………………………………………………………Page 346……………………………………………………………
324 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
type。 The parameter identifier is a string that is used to search the Dictionary data member
_availableTypes。 If the identifier exists in _availableTypes; the ConfigurationInfo instance is
retrieved and used to instantiate the type。 If the identifier does not exist; an exception is thrown。
The bolded code is the special code because it is unlike what you have encountered thus
far in the book。 Built into is the ability to dynamically execute code; as illustrated here。
The first bolded line makes the reflection ability available; and the second is used to load the
assembly。 So; for example; if the parameter identifier equaled Impl1 (remember; this is one
of the keys in the configuration file element); the first bolded line would refer
ence and dynamically load the assembly Implementations1。dll。 However; and here is the
catch; the assembly can be loaded dynamically only if Implementations1。dll exists in the local
directory or the GAC。 As an alternative; you could specify th