Dynamic Discovery of Types


The dynamic discovery and instantiation of types is becoming increasingly important in modern software architectures. Why? Traditionally, programming languages and systems held to the notion that as much as possible should be known at compile time. It is true that the more information is available to the compiler, the potentially more type-safe and efficient the executable code could be. But it is also true that this approach leads to platform-specific code that is very difficult to migrate and execute on different systems. With the recent widespread use of distributed systems, such as the Internet, more dynamic facilities have become a necessity. In addition, today's programs must frequently deal with types that are developed after the original program was developed. As an example, consider programs such as the ActiveX Test Container, which is capable of interacting with COM controls created by many developers.

Both CORBA and COM provide facilities for dynamic type discovery, instantiation, and invocation, including the Dynamic Invocation Interface (DII) and IDispatch . The .NET Framework provides dynamic type discovery through its reflection facilities. In addition, it enables developers to create both local and remote objects at runtime. That is, the Activator class provides the functionality to dynamically create an instance of a class. The Activator class, which is a subtype of Object , has four methods :

  • CreateComInstanceFrom : Creates an instance of a COM object and returns a handle to that object.

  • CreateInstance : Creates an instance of an object and returns a reference to that object.

  • CreateInstanceFrom : Creates an instance of an object and returns a handle to that object, as opposed to returning a reference to that object.

  • GetObject : Creates a proxy object to an already running, well-known remote object. Methods then invoked on the proxy object will be forwarded to the remote instance.

Two of the CreateInstance methods ”the ones ending in From ”deal with creating types when the metadata describing the types is located in another application domain. Application domains are covered in Chapter 4, so explaining the reasons behind the use of these methods is a little premature at this point. For now, simply consider an application domain to be a subprocess. If types are passed between multiple application domains, then each application domain may need to know about a large number of different types. As an alternative, application domains can pass handles to objects; in such a case, only when an object is extracted from its handle is the metadata required to be loaded into that specific application domain.

The CreateInstance method, of which several variations exist, is the principal method for dynamically creating instances of a type. In this method, one parameter identifies the type of the object to be created. This type is specified by using either a Type object or a string that represents the type's name. When a string is used to specify the type's name, it may be necessary to pass the name of the assembly containing the type as well. Variations of the CreateInstance methods may take the following parameters:

  • Constructor arguments ”an array of objects used as the argument list to the constructor call

  • Binding information ”for selecting among multiple candidates

  • Culture information

  • Security requirements

Listing 3.7 demonstrates how to create a dynamic object of type String . This example is greatly simplified, as both the name of the type and the method to be invoked are specified in the source code. This program creates an instance of a string after creating an array of characters to be passed to the constructor. Next, it retrieves the MethodInfo object for the Insert method that takes an integer and a string as parameters. Finally, it invokes this method and writes the result to console.

Listing 3.7 Creating a dynamic String object
 using System; using System.Reflection; namespace DynamicInstantiation {   class Sample   {     static void Main(string[] args)     {       Type t = Type.GetType("System.String");       Object[] argumentArray = new Object[1];       Char [] charArray =               new Char[]{'H', 'e', 'l', 'l', 'o'};       argumentArray[0] = charArray;       Object dynamicObject =              Activator.CreateInstance(t, argumentArray);       Type[] typeOfParameters = new Type[2];       typeOfParameters [0] = Type.GetType("System.Int32");       typeOfParameters [1] = Type.GetType("System.String");       MethodInfo methodName =                   t.GetMethod("Insert",typeOfParameters );       argumentArray  = new Object[2];       argumentArray [0] = 5;       argumentArray [1] = " World!";       Console.WriteLine("Invoking this method: " +                         methodName);       Console.WriteLine(methodName.Invoke(dynamicObject,                                           argumentArray));     }   } } 

Executing Listing 3.7 produces the following output:

 Invoking this method: System.String Insert(Int32,  System.String) Hello World! 


Programming in the .NET Environment
Programming in the .NET Environment
ISBN: 0201770180
EAN: 2147483647
Year: 2002
Pages: 146

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