Published: 27 Oct 2010
By: Xianzhong Zhu
Download Sample Code

In this last article of this series, we will learn what to do with reflection. But before making the topic more interesting, we'll first look at how to dynamically create an object.

Contents [hide]

The C# 4.0 Reflection Programming series

  • Part 1 An introduction to Reflection in C#.
  • Part 2 As introduced in the first article, the most typically-used tools associated with .NET reflection are: the Type class and Assembly class related members. In this second article, we are going to pick up the .NET reflection tools to set up more samples to explore the wide and extensive use of reflection.
  • Part 3 In the previous article, we used the reflection to obtain the information of an assembly, module, type, and type members. In this article, we'll turn to discuss another important aspect related to reflection-Attribute programming. We are going to first look at the mostly-used .NET built-in Attributes, and then try to write a custom Attribute. At last, we'll rest upon reflection to acquire the custom attribute info.
  • Part 4 In this last article of this series, we will learn what to do with reflection. But before making the topic more interesting, we'll first look at how to dynamically create an object.
  • Introduction

    In the previous articles, we first introduced what is the reflection, and then view the information of target types using reflection, and learn how to create custom attributes, as well as use reflection to traverse them. It can be concluded that in these three sections, we studied what is the reflection. In this last article of this series, we will learn what to do with reflection. But before making the topic more interesting, we'll first look at how to dynamically create an object.

    Dynamic Creation of Objects

    Launch Visual Studio 2010 and create a new Console project, called Reflection4. Then, add a general C# class named Calculator.

    Listing 1: The demo class - Calculator

    In the first half of this article, we'll mainly use this class for illustration of most of the reflection related operations.

    Create objects with non-argument constructor

    As is seen, the above class is very simple. It contains two constructors: one is with one parameter; the other is with no argument. We first take a look at how to create objects using the non-argument constructor through the reflection. There are two ways to create objects, one of which is to use the CreateInstance method of the Assembly:

    Well, the first parameter of the CreateInstance method represents the string name of type instance to create, while the second parameter indicates whether the string name is case sensitive or not. Note the CreateInstance method returns an Object, which means if you want to use this object you need to make a type conversion.

    Another way to create objects is to call the static method CreateInstance of the Activator class:

    Here, the first argument of the CreateInstance method represents the name of the assembly (null means the current assembly); the second parameter corresponds to the type name you want to create. Also note that the Activator.CreateInstance method returns an object of ObjectHandle, which has to make an Unwrap() invocation to return Object type. And thus, it can be cast into the type we need (in this case is Calculator). ObjectHandle is included in the System.Runtime.Remoting namespace, which is relevant to the Remoting operation. In fact, the ObjectHandle class is just a type which encapsulates the original type for ease of marshalling. More info about it can be found in MSDN.

    Create objects using constructors with parameters

    If we want to create objects via constructor having arguments, we can use the overloaded CreateInstance() method of Assembly:

    Now, let's take a good look at the parameters the CreateInstance method needs to provide:

    1. The first two has been introduced in the previous section;
    2. BindingFlags, also used previously, is used for restrict the search for members of the type. Here Default means not using the BingdingFlags provided retrieving strategies (you can take it as null, but BindingFlags is a value type, it is not possible with a value of null. Anyway, there must be a default value, and Default is its default value);
    3. The next parameter is Binder, which encapsulates the rules that the CreateInstance method uses to bind objects (Calculator in our case). We almost always pass null, actually using a predefined DefaultBinder;
    4. The next parameter is an Object[] array type, which contains the parameters that we pass in. Constructors with parameters will use them;
    5. The last parameter is a CultureInfo type, which contains information about the language and culture.

    Dynamically Invoke Methods

    Next, let's look at how to dynamically call a method. Note here it is not meant to cast the above dynamically-created object from the Object type into the Calculator type and then call its methods. If so, there will be no difference with the common call. Let's start the method invocation using the .Net reflection approach. Before proceeding, let's first add two methods to the Calculator class: one is an instance method; the other is a static method:

    On the whole, dynamically calling the methods via .NET reflection there are two ways:

    1. Call the InvokeMember method of the Type object, passing in the object of which you want to call the methods (i.e. just the dynamically created instance of the Calculator class), as well as specifying BindingFlags as InvokeMethod. According to the method signature, you may also need to pass associated parameters.

    2. First obtain the method object (which is the MethodInfo object) to call through the GetMethod method of the Type object. Then, call the Invoke method on the method object. According to the method signature, you may also need to pass parameters.

    It should be noted that the use of InvokeMember is not limited to call the object's method. It can also be used to obtain the object's fields, properties, etc., all of which take the similar means. This article only delves into the most commonly-seen method calling.

    Call methods using InvokeMember

    Let's first check out the first method. The required code is very simple, only two lines.

    Note that the obj has been created in the previous section, which is an instance of type Calculator.

    Now, if you run the above sample you will get the following output:

    Invoke Instance Method:

    [Add]: 3 plus 5 equals to 8

    The result is 8

    In the above InvokeMember method, the first parameter describes the name of the method you want to call. The second parameter shows it is make the method invocation (because InvokeMember is very powerful, which not only can be used to call the method but also can get/set properties, fields. and so on. Related details can be found in MSDN). The third parameter is Binder, with null meaning using the default Binder. The fourth argument specifies making call upon this object (obj is an instance of type Calculator). The final parameter is an array type, specifying the method accepted parameters.

    Next, let's look at the static method related method calling.

    Now, if you again run the preceding sample you will get the following output:

    Invoke Static Method:

    [Add]: 6 plus 9 equals to 15

    Let's make some comparison with above. First, the fourth parameter is typeof(Calculator), rather than a Calculator instance. This is very easy to understand because we are calling a static method which is not based on an instance of a specific type, but on the type itself. Secondly, because our static method needs to provide two parameters we pass these two parameters in the form of an array.

    Call methods using MethodInfo.Invoke

    Now, let's explore the second way to dynamically call a method. First, we should get an instance of MethodInfo. Then, call the Invoke method of that instance. Let's check out the concrete operation:

    Now, if you run the preceding sample you will get the following output:

    Invoke Instance Method:

    [Add]: 3 plus 5 equals to 8

    Press any key to continue...

    Note in the second line in the above code, we first use the method GetMethod to get an object MethodInfo, specifying the BindingFlags flags being Instance and Public. Because there are two methods named "Add" here we must specify the searching conditions. Then, we use the Invoke method to call the Add method, with the first parameter obj being the instance of Calculator created previously (meaning creating methods upon this instance), with the second parameter being null, that means the method does not need parameters.

    Next, let' continue to look at how to use this way to call a static method:

    Now, if you run the preceding sample you will get the following output:

    Invoke Static Method:

    [Add]: 6 plus 9 equals to 15

    Similar with the above, in the GetMethod method, we specify one of the searching criteria being BindingFlags.Static, rather than BindingFlags.Instance, because the Add method we are to call is static. In the Invoke method, note that the first argument can not be an instance of Calculator but the Type type of Calculator or just null, because static methods do not belong to a specific instance.

    Through the above examples, it can be concluded that we can use reflection to achieve the maximum degree of polymorphism. For example, you can place a DropDownList control on an ASP.NET page, and then specify the value of its Items property as the methods of some class, and finally in the SelectedIndexChanged event handler of the DropDownList control use the value of Value to call the selected method of the class. In the past, you have to write some if-else (even nested) statements to determine the value returned by the DropDownList control, and then decide which method to call according to the value. Using this method, before the code is running (or before the user selects an option) the compiler does not know which method will be called. This is often the so-called late binding.

    Traverse the System.Drawing.Color Structure

    Till now, we have brought to you too much about the theory. Let's build an interesting example. We all know that in the ASP.NET environments, color settings of the controls, such as ForeColor, BackColor, etc., are all supported via a System.Draw.Color structure type. In some cases, however, we need to use a custom color. For example, we can use something like Color.FromRgb (125, 25, 13) to create a specified color value. But sometimes we feel a bit troublesome because this group of figures is not intuitive enough that we even need to paste this value into PhotoShop to see which color on earth it corresponds to.

    At this time, we may want to use the default color the Color structure provides. That is, we can use the 141 static properties related to color. But, these values are still based on the color name, such as DarkGreen. This is not intuitive, too. If there is some way to render these named colors onto the page in the form of color block it will be great. Next, let's try to achieve this dream with the help of .NET reflection.

    Now we look at the implementation process.

    Create an ASP.NET sample page

    Start up Visual Studio 2010, create a basic ASP.NET Web Application, and name it CustomColorTest. Then, add a new Web Form named Color.aspx and add some style definition in the head part to control the final rendering. Then, drag a Panel control onto the page. The final markup code looks like the following.

    In the above cascade style sheet definition, what should be noted is the #pnColors div block, which defines the style in which the color on the page will be displayed. The Panel control whose Id property is pnHolder is used to load our dynamically generated divs.

    Our idea is like this: we will add a series of div elements in the Panel control, each of which corresponds to the color block that we are going to show on the page. To do this, we can set the div's text to the color names and RGB values, while we set its background color to the corresponding color (the other styles of the color blocks, such as width, border, etc. have been defined in the <head/>.)

    We know that in Asp.Net there is not a Div control, but only an HtmlGenericControl control. Next, we will define a custom Div class in the behind code and let it inherited from HtmlGenericControl.

    Listing 2: The custom Div class

    As we described earlier, the Div class accepts a Color type as the only constructor parameter. And then, in the constructor, first set its InnerHtml property to the various color names and color values (through the R, G, and B properties of the Color structure). Finally, set the div's background color to the corresponding RGB color.

    Note in the above case there may be some color that is very dark. In this case, if we continue to use the dark foreground color, then the text will look dizzy. So I added an if statement: if the background is dark, then we set foreground color brighter.

    OK, till now what left to do is simple. We only need to invoke the above class with the help of .NET reflection.

    The above code is very straightforward. First, create a Div list, to save the color blocks to be created. Then, get the Type instance of the Color type. Then, we use the GetProperties method together with the BindingFlags bit flags to obtain all the static public properties. And then traverse the properties, and use the InvokeMember method to get the property value. Because the returned value is an Object type, we need to cast it into a Color type. Note here the BindingFlags bit flag of the InvokeMember method is specified as GetProperty, meaning getting the property value. The fourth parameter is set to typeof(Color), because the color attribute (such as DarkGreen) is static, not specific to a particular instance - if it is an instance, then you need to pass in the instance of the type that calls this property. Next, we create the div elements based on the related color, add it to the list. Finally, we traverse the list and add the div elements to the Panel control with Id being pnColors.

    Well now, let's build the above CustomColorTest and preview the web page CustomColorTestPage.aspx. You should see results like Figure 1 below.

    Figure 1: Sort the color using the color name

    Sort the color using the color name

    Sort the color blocks

    The above page CustomColorTestPage.aspx looks a bit chaotic, doesn't it? This is because the list is roughly sorted by color name (except for Transparnet). In fact, we can better sort the list based on color. For brevity, here I will give the detailed implementation process, rather than dwell upon the abstract sort theory. Note this section has nothing to do with the reflection, if you are already familiar with sorting, you can skip.

    Now, open again page CustomColorTestPage.aspx and add a control RadioButtonList onto the page, setting its AutoPostBack property to true. Our target is to sort the color blocks not only according to the name but according to the color values.

    The RadioButtonList control related markup code is as follows:

    In the behind code, add an enum type as the criteria for sorting:

    Next, let's rewrite the Div class to add a ColorValue field, which represents the value of the color, as well as create a nested class ColorComparer, and two methods named GetComparer:

    Now, in the Page_Load event handler, we should accordingly add the related statements to get the current sort criteria:

    Before outputting the list to the page, we should call the Sort method of the list:

    Well, all the work is complete. Rebuild the web project and preview the page again and you will see something similar to the following Figure 2.

    Figure 2: Sort the color using the color name or color value

    Sort the color using the color name or color value

    Note that we can now sort the color blocks according to the name or color value.

    Summary

    In this series of articles, we've discussed many basic concepts and related operations supported by .Net reflection functionality. In this last article, we've first learned the two most common ways to dynamically create an object, and then discussed the use of the two important methods, Type.InvokeMember and MethodInfo.Invoke, with which to call the instance methods and static methods of a given type. Finally, we studied a sample application - traverse the System.Drawing.Color via .NET reflection support, and output the color values. Anyway, as mentioned in the first article, interesting things related to .NET reflection have just begun...

    The C# 4.0 Reflection Programming series

  • Part 1 An introduction to Reflection in C#.
  • Part 2 As introduced in the first article, the most typically-used tools associated with .NET reflection are: the Type class and Assembly class related members. In this second article, we are going to pick up the .NET reflection tools to set up more samples to explore the wide and extensive use of reflection.
  • Part 3 In the previous article, we used the reflection to obtain the information of an assembly, module, type, and type members. In this article, we'll turn to discuss another important aspect related to reflection-Attribute programming. We are going to first look at the mostly-used .NET built-in Attributes, and then try to write a custom Attribute. At last, we'll rest upon reflection to acquire the custom attribute info.
  • Part 4 In this last article of this series, we will learn what to do with reflection. But before making the topic more interesting, we'll first look at how to dynamically create an object.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Xianzhong Zhu

    I'm a college teacher and also a freelance developer and writer from WeiFang China, with more than fourteen years of experience in design, and development of various kinds of products and applications on Windows platform. My expertise is in Visual C++/Basic/C#, SQL Server 2000/2005/2008, PHP+MyS...

    This author has published 81 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    C# 4.0 Reflection Programming - Part 1
    An introduction to Reflection in C#.
    C# 4.0 Reflection Programming - Part 2
    As introduced in the first article, the most typically-used tools associated with .NET reflection ar...
    C# 4.0 Reflection Programming - Part 3
    In the previous article, we used the reflection to obtain the information of an assembly, module, ty...
    Understanding and Using Extension Methods
    Extension methods were new to C# 3.0. They allow you to add a method to an existing type without hav...
    Introduction to C# 3.0 features
    C# 3.0 introduced some of very useful features built on top of 2.0. This article explains the usage,...

    You might also be interested in the following related blog posts


    Introducing SharePoint 2010 Training at U2U read more
    The Underground at PDC read more
    Building A Product For Real read more
    My History of Visual Studio (Part 6) read more
    F# in VS2010 read more
    My History of Visual Studio (Part 5) read more
    BeginDialOut with Office Communicator Clients read more
    DotNetNuke Fusion Results for Q3 read more
    GiveCamps Get a new Sponsor read more
    Announcing the WebsiteSpark Program read more
    Top
     
     
     

    Please login to rate or to leave a comment.