Creating Type Instances by Using ConstructorInfo


Creating Type Instances by Using ConstructorInfo

Once you have a System.Type object instance, you can use it to create an instance of the type it represents. This can be done by querying for a ConstructorInfo object. The ConstructorInfo class is used to discover the attributes of a constructor, and it provides access to constructor metadata. Most importantly, a ConstructorInfo instance can be used to invoke a type's constructor.

Before we start invoking constructors, let's discuss how you can get a hold of one of these powerful objects. The Type class provides two methods for retrieving ConstructorInfo s: GetConstructors and GetConstructor .

Using the GetConstructors Method

The GetConstructors method comes in two flavors. The easiest flavor to use accepts no parameters and returns all of the public constructors defined for the type. You can iterate through the array of ConstructorInfo objects and then invoke the constructor you deem appropriate to use. We will discuss invoking the constructor shortly. Listing 13.7 demonstrates how to use GetConstructors to retrieve a list of all public constructors.

Listing 13.7
 C# public class Type_GetConstructors {   public int integer;   public Type_GetConstructors() : this(0) {   }   public Type_GetConstructors(int anInt) {     integer = anInt;   } } public class Test {   public static void Main() {     Type t = typeof(Type_GetConstructors);     ConstructorInfo[] cstors = t.GetConstructors();     foreach(ConstructorInfo cstor in cstors) {       MessageBox.Show(         String.Format(         "Found a {0} constructor that takes {1} parameters",         (cstor.IsPublic ? "Public" : "Non-Public"),         cstor.GetParameters().Length));     }   } } VB Module Module1     Sub Main()         Dim t As Type         Dim cstors As ConstructorInfo()         Dim ndx As Int32         Dim tgc As New Type_GetConstructors()         t = tgc.GetType()         cstors = t.GetConstructors()         For ndx = 0 To cstors.Length - 1             Dim visibility As String             If cstors(ndx).IsPublic Then                 visibility = "Public"             Else                 visibility = "Non-Public"             End If             MessageBox.Show( _               String.Format( _               "Found a {0} constructor that takes {1} parameters", _                visibility, _                cstors(ndx).GetParameters().Length))         Next ndx     End Sub     Public Class Type_GetConstructors         Public m_Int As Int32         Public Sub New()             m_Int = 0         End Sub         Public Sub New(ByVal int As Int32)             m_Int = int         End Sub     End Class End Module 

The Type class also provides an overload of the GetConstructors method that takes one parameter. This parameter is of the type BindingFlags , an enumeration that controls the way in which the search for members and types is conducted by reflection. As we investigate reflection more in this chapter, you will see the BindingFlags enumeration appear again and again. This enumeration is defined with a FlagsAtribute attribute that allows a bitwise combination of its member values. Table 13.1 contains the list of BindingFlags values that are appropriate to pass to the GetConstructors method and how they affect the search.

Table 13.1. BindingFlags Members Relevant to the GetConstructors Method

MEMBER

NAME DESCRIPTION

Default

Specifies no binding flag

Instance

Specifies that instance constructors are to be included in the search

NonPublic

Specifies that nonpublic constructors are to be included in the search

Public

Specifies that public constructors are to be included in the search

Static

Specifies that static constructors are to be included in the search

Listing 13.8 demonstrates how to use GetConstructors to search for all constructors of a given type. This will include both static and instance constructors as well as both public and nonpublic constructors.

Listing 13.8
 C# public class ConstructorInfo_GetConstructors {   public static int staticInteger;   public int integer;   public ConstructorInfo_GetConstructors () : this(0) {   }   public ConstructorInfo_GetConsructors (int anInt) {     integer = anInt;   }   private ConstructorInfo_GetConsructors (int x, int y) {     integer = x;     staticInteger = y;   }   static ConstructorInfo_GetConsructors () {     staticInteger = 13;   }   public static void Main() {     Type t = typeof(ConstructorInfo_GetConstructors);     ConstructorInfo[] cstors =       t.GetConstructors(BindingFlags.Instance  BindingFlags.Static                          BindingFlags.Public  BindingFlags.NonPublic);     foreach (ConstructorInfo cstor in cstors) {         MessageBox.Show(         String.Format         ("Found a {0} {1} constructor that takes {2} parameters",           (cstor.IsStatic ? "Static" : "Instance"),           (cstor.IsPublic ? "Public" : "Non-Public"),           cstor.GetParameters().Length));     }   } } VB Module Module1     Public Class ConstructorInfo_GetConsructors         Public Shared sharedInteger As Int32         Public m_Int As Int32         Public Sub New()             m_Int = 0         End Sub         Public Sub New(ByVal anInt As Int32)             m_Int = anInt         End Sub         Public Sub New(ByVal x As Int32, ByVal y As Int32)             m_Int = x             sharedInteger = y         End Sub         Shared Sub New()             sharedInteger = 13         End Sub     End Class     Sub Main()         Dim t As Type         Dim cstors As ConstructorInfo()         Dim ndx As Int32         Dim cigc = New ConstructorInfo_GetConsructors()         t = cigc.GetType()         cstors = t.GetConstructors(BindingFlags.Instance Or _                                    BindingFlags.Static Or _                                    BindingFlags.Public Or _                                    BindingFlags.NonPublic)         For ndx = 0 To cstors.Length - 1             Dim visibility As String             Dim isStatic As String             If cstors(ndx).IsPublic Then                 visibility = "Public"             Else                 visibility = "Non-Public"             End If             If cstors(ndx).IsStatic Then                 isStatic = "Static"             Else                 isStatic = "Instance"             End If             MessageBox.Show( _              String.Format( _              "Found a {0} {1} constructor that takes {2} parameters", _              visibility, _              isStatic, _              cstors(ndx).GetParameters().Length))         Next ndx     End Sub End Module 

Retrieving Individual ConstructorInfo Objects with GetConstructor

So far we have been searching for constructors based on visibility and scope. There will be times when you need to query for a constructor based on the number and type of parameters the constructor accepts. For instance, if you are building a custom serializer, you may need to search for a default constructor with which to construct an object being deserialized. The Type class provides the GetConstructor method to provide this functionality. The GetConstructor method returns a single ConstructorInfo object, or else null if the constructor could not be found. The method takes one parameter, a Type array that represents the number, order, and type of the parameters for the constructor to get. You can pass in an empty array of the type Type to get a constructor that takes no parameters. Do not pass in null for this; it would result in an ArgumentNullException . It is important to note that GetConstructor will look for public instance constructors and cannot be used to obtain a class initializer (static constructor). Listing 13.9 demonstrates how to use GetConstructor to query for a public instance constructor that takes zero parameters.

Listing 13.9
 C# public class ConstructorInfo_GetConstructor {   public static int staticInteger;   public int integer;   public ConstructorInfo_GetConstructor () : this(0) {   }   private ConstructorInfo_GetConstructor (int anInt) {     integer = anInt;   }   static ConstructorInfo_GetConstructor () {     staticInteger = 13;   }   public static void Main() {     Type t = typeof(ConstructorInfo_GetConstructor);     ConstructorInfo cstor = t.GetConstructor(new Type[0]);     if(cstor == null)       MessageBox.Show("No constructor found.");     else       MessageBox.Show         ("Found a public instance constructor with no params");   } } VB Module Module1     Public Class ConstructorInfo_GetConstructor         Public Shared sharedInteger As Int32         Public m_int As Int32         Public Sub New()             m_int = 0         End Sub         Public Sub New(ByVal anInt As Int32)             m_int = anInt         End Sub         Shared Sub New()             sharedInteger = 13         End Sub     End Class     Sub Main()         Dim t As Type         Dim cstor As ConstructorInfo         Dim empty() = New Type() {}         Dim cigc As New ConstructorInfo_GetConstructor()         t = cigc.GetType()         cstor = t.GetConstructor(empty)         If cstor Is Nothing Then             MessageBox.Show("No constructor found.")         Else             MessageBox.Show _               ("Found a public instance constructor with no params")         End If     End Sub End Module 

Creating Object Instances with the ConstructorInfo Class

Now that we know how to find a ConstuctorInfo , we are ready to use it to create an object instance. The ConstructorInfo class provides the Invoke method to invoke the constructor it represents. The Invoke method takes one parameter, an array of objects that represent values of the parameters to be passed to the constructor. The values should match the number, type, and order of the parameters for the constructor reflected by the ConstructorInfo object. Before calling the constructor, Invoke verifies that the parameters are valid. If the constructor takes no parameters, then you should pass in an empty array of objects. The ConstructorInfo method returns a reference to an object, so you must cast it to the correct type. Listing 13.10 code shows how to find a specific constructor, invoke the constructor, and inspect the new object instance.

Listing 13.10
 C# public class ConstructorInfo_Invoke {   public int integer;   public string str;   public ConstructorInfo_Invoke () : this(0, string.Empty) {   }   public ConstructorInfo_Invoke (int int1, string str1) {     integer = int1;     str = str1;   }   public static void Main() {     Type[] ts = {typeof(int), typeof(string)};     Type t = typeof(ConstructorInfo_Invoke);     ConstructorInfo cstor = t.GetConstructor(ts);     if (cstor == null) {       MessageBox.Show("Could not create the object instance");       return;     }     object[] os = {13, "This object was created with reflection."};     object objTest = cstor.Invoke(os);     ConstructorInfo_Invoke test = objTest as ConstructorInfo_Invoke;     if( test == null) {       MessageBox.Show("Could not cast the object to it correct type");       return;     }     MessageBox.Show("New ConstructorInfo_Invoke object created:\n" +                     "\tinteger: " + test.integer +                     "\n\tstr: " + test.str);   } } VB Module Module1     Public Class ConstructorInfo_Invoke         Public m_int As Int32         Public str As String         Public Sub New()             m_int = 0             str = String.Empty         End Sub         Public Sub New(ByVal anInt As Int32, ByVal aStr As String)             m_int = anInt             str = aStr         End Sub     End Class     Sub Main()         Dim t As Type         Dim ts() = New Type() {0.GetType(), String.Empty.GetType()}         Dim os() = New Object() { _                      13, _                      "This object was created with reflection"}         Dim ret As Object         Dim cstor As ConstructorInfo         Dim cii As New ConstructorInfo_Invoke()         t = cii.GetType()         cstor = t.GetConstructor(ts)   If cstor Is Nothing Then             MessageBox.Show("Could not create the object instance")             Return         End If         os(0) = 13         os(1) = "This object was created with reflection"         ret = cstor.Invoke(os)         Dim test = CType(ret, ConstructorInfo_Invoke)         If test Is Nothing Then             MessageBox.Show _               ("Could not cast the object to its " & _                "correct type instance")             Return         End If         MessageBox.Show("New ConstructorInfo_Invoke object created:"& _                         Chr(13) & "integer: " & test.m_int & _                         Chr(13) & "str: " & test.str)     End Sub End Module 


Microsoft.NET Compact Framework Kick Start
Microsoft .NET Compact Framework Kick Start
ISBN: 0672325705
EAN: 2147483647
Year: 2003
Pages: 206

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