Http://www.csharpwin.com/csharpspace/9314r9141.shtml dynamically creates an object in the previous section, we first understand reflection, then use reflection to view the type information, learn how to create a custom feature, and use reflection to traverse it. We can say that in the first three sections, we learn what reflection is. In the following sections, we will learn what reflection can do. Before you start a more interesting topic, let's take a look at how to dynamically create an object. Create a console project called reflection4 (because this article is part4, you can also name it ). Then, add a demo class. This article describes the operations of this demo class: public class calculator {private int X; private int y; Public calculator () {x = 0; y = 0;} public calculator (int x, int y) {This. X = x; this. y = y ;}} 1. it is very simple to create an object using a non-parameter constructor. It contains two constructor functions: a constructor with parameters and a constructor without parameters, let's first look at how to create an object using a non-parameter constructor through reflection. There are two methods to create an object. One is to use the createinstance method of assembly: Assembly ASM = assembly. getexecutingassembly (); object OBJ = ASM. createinstance ("reflection4.calculator", true); // output: the first parameter of calculator () invokedcreateinstance represents the string name of the type instance to be created, the second parameter indicates whether it is case-insensitive (ignore case ). Note that createinstance returns an object, which means that if you want to use this object, you need to perform a type conversion. Another way to create an object is to call the static method createinstance: objecthandle handler = activator of the activator class. createinstance (null, "reflection4.calculator"); object OBJ = handler. unwrap (). The first parameter of createinstance indicates the Assembly name. If it is null, it indicates the current Assembly. The second parameter indicates the type name to be created. Activator. createinstance returns an objecthandle object. Only one unwrap () operation is required to return the object type, which can be forcibly converted to the required type (calculator in this example ). Objecthandle is included in system. runtime. in the remoting namespace, we can see that it is related to remoting. I haven't done much research on remoting for the moment. Now we only need to know that we can create objects in this way. 2. if you want to create an object using a parameter constructor, you can use the createinstanc () method of assembly to create an object: // create object Assembly ASM = assembly by using a parameter constructor. getexecutingassembly (); object [] parameters = new object [2]; // defines the parameter parameters [0] = 3 required by the constructor; Parameters [1] = 5; object OBJ = ASM. createinstance ("reflection4.calculator", true, bindingflags. default, null, parameters, null, null); // output: calculator (int x, int y) invoked let's take a look at createinstanc E. parameters to be provided: the first two have been described in the previous section; bindingflags is also used in the previous section, which is used to limit the search for type members. Specify default here, which means that the bingdingflags policy is not used (you can think of it as null, but bindingflags is of the value type, so it cannot be null and must have a default value, and this default is its default value); the next parameter is binder, which encapsulates the rules of the createinstance binding object (calculator), and we will almost always pass null in, in fact, the predefined defaultbinder is used. Next, an object [] array type contains the parameters we pass in. constructors with parameters will use these parameters; the following parameter is of the cultureinfo type, which contains information about language and culture (To put it simply, when tostring ("C") should display "¥ ", when should I display "$ "). Next, let's take a look at how to call a method dynamically. Note: The call discussed in this article does not convert the dynamically created object from the object type to the calculator type before calling the method. This is no different from the conventional call. net Reflection Method to call the method. Before proceeding, we add two methods for calculator: one instance method and one static method: Public int add () {int Total = 0; Total = x + y; console. writeline ("INVOKE instance method:"); console. writeline (string. format ("[add]: {0} plus {1} equals to {2}", X, Y, total); Return total ;} public static void add (int x, int y) {int Total = x + y; console. writeline ("INVOKE static method:"); console. writeline (string. format ("[add]: {0} plus {1} equals {2} ", X, Y, total);} There are two methods to call a method: Call the invokemember () method on a type object, pass the object on which you want to call the method (that is, the calculator type instance that was just created dynamically), and specify bindingflags as invokemethod. You may also need to pass parameters based on the method signature. Use the getmethond () method of the type object to obtain the method object to be called, that is, the methodinfo object, and then call the invoke method on the object. You may also need to pass parameters based on the method signature. It should be noted that the use of invokemember is not limited to calling object methods, but can also be used to obtain object fields and attributes. The methods are similar. This article only describes the most common call methods. 1. to use invokemember to call a method, Let's first look at the first method. The code is very simple and requires only two lines (note that obj has been created in the previous section and is an instance of the calculator type): type T = typeof (calculator ); int result = (INT) T. invokemember ("add", bindingflags. invokemethod, null, OBJ, null); console. writeline (string. format ("the result is {0}", result); output: invoke instance method: [add]: 3 plus 5 equals to 8 the result is 8 in the invokemember method, the first parameter indicates the name of the method to be called. The second parameter indicates the method to be called (because invokemember is very powerful You can also obtain/set attributes and fields. For details about this enumeration, see Part.2 or msdn. The third parameter is binder. The default binder is used for null; the fourth parameter description is called on this object (obj is an instance of the calculator type); the last parameter is an array type, indicating the parameters accepted by the method. Let's take a look at how to call static methods: object [] parameters2 = new object [2]; parameters2 [0] = 6; parameters2 [1] = 9; T. invokemember ("add", bindingflags. invokemethod, null, typeof (calculator), parameters2); output: invoke static method: [add]: 6 plus 9 equals to 15. let's compare it with the above: first, the fourth parameter is typeof (calculator), which is no longer a calculator instance type. This is easy to understand because we call a static method, it is not based on a specific type instance, but on the Type itself. Secondly, because our static method requires two parameters, so we passed the two parameters in the form of arrays. 2. use methodinfo. let's look at the second method for calling the invoke method. First we get a methodinfo instance and then call the invoke method of this instance. Let's take a look at how to do it: type T = typeof (calculator ); methodinfo MI = T. getmethod ("add", bindingflags. instance | bindingflags. public); Mi. invoke (OBJ, null); output: invoke instance method: [add]: 3 plus 5 equals to 8 press any key to continue... in the second line of the code, we first use the getmethod method to obtain a method object methodinfo and specify bindingflags as instance and public, because there are two methods named "add ", therefore, specifying search conditions is required. Then, the add method is called using invoke (). The first parameter obj is the calculator type instance created earlier, indicating that the method is created on the instance. The second parameter is null, parameters are not required for the description method. Let's look at how to call the static method in this way: type T = typeof (calculator); object [] parameters2 = new object [2]; parameters2 [0] = 6; parameters2 [1] = 9; methodinfo MI = T. getmethod ("add", bindingflags. static | bindingflags. public); Mi. invoke (null, parameters2); // mi. invoke (T, parameters2); the output can also be: invoke static method: [add]: 6 plus 9 equals to 15, which is similar to the preceding one. In the getmethod () method, we specify to search for bindingflags. static instead of bindingflags. P Ublic, because we want to call the static add method. In the invoke () method, note that the first parameter cannot be passed in the calculator type instance, but should be passed in the type of the calculator or directly null. Because the static method does not belong to an instance. Note: The above example shows that reflection can achieve the maximum polymorphism. For example, you can place a dropdownlist control on the page, specify its items value as the name of a class method, and then use the value to call the class method in the selectedindexchanged event. In the past, you had to write some if else statements, first judge the value returned by dropdownlist, and then decide which method to call based on the value. In this way, the compiler does not know which method will be called before the code is run (or before the user selects an option), which is also known as late binding ). Coding4fun: traverse system. drawing. we have already talked about many basic methods and theories in the color structure. Now let's do something interesting: Everyone knows that in ASP. net controls, such as forecolor and backcolor, are all system. draw. color structure type. In some cases, we need to use a custom color, so we will use a method like this to create a color value for color. fromargb (, 25, 13. But sometimes we may feel a little troublesome, because this number is too intuitive, and we even need to paste this value to Photoshop to see what it looks like. At this time, we may want to use the default color provided by the color structure, that is, its 141 static attributes, but these values are still given in the form of names, such as darkgreen, it is not intuitive enough. If we can output them to the page in the form of color blocks, it will be much more convenient for us to view them and it will be more convenient to use in the future. I have implemented it, you can click the following link to view: effect preview: http://www.tracefact.net/demo/reflection/color.aspx basic implementation now let's take a look at the implementation process: first create page color. aspx (or other names), add some style control pages to the head, and drag and drop a panel control. Note that the # pncolors Div section defines the color block style displayed on the page. The panel control with ID pncolors is used to load our dynamically generated Div.
Coding4fun: Uses reflection to traverse the system. Drawing. Color Structure
Note: If you name the page as color. aspx, You need to modify the class name in the Post-code file, such as reflection_color, and change the class name to inherits = "reflection_color" at the top of the page. Otherwise, the name conflict may occur. The next step is to add a series of divs in phcolors, which are the color blocks to be displayed on the page. We set the text of the DIV to the color name and the RGB value, and set its background color to the corresponding color (other styles of the color block, for example, width, border, and width are already defined in the head ). We know that in ASP. NET, there is no Div control, only htmlgenericcontrol. At this time, we 'd better define a div so that it inherits from htmlgenericcontrol. Public class Div: htmlgenericcontrol {private string name; Public Div (color C): Base ("Div") // call the base class constructor to create a div {This. name = C. name; // color name // set text this. innerhtml = string. format ("{0}
RGB ({1}, {2}, {3}) ", name, C. r, C. g, C. b); int Total = C. R + C. G + C. b; If (total <= 255) // if the background color is too dark, the foreground color is changed to the clear color. This. style. add ("color", "# Eee"); // set the background color this. style. add ("background", String. format ("RGB ({0}, {1}, {2})", C. r, C. g, C. b) ;}} as described above, this Div accepts a color type as a constructor parameter, and then in the constructor, first, the text is set to the color name and each color value (obtained through the R, G, and B attributes of the color structure ). Then, the background color of the DIV is set to the RGB color. Note: In the above if (total <= 255), some colors may be very dark. If the black foreground color is used in this case, the text will not be clear, so I added a judgment, if the background is too dark, the foreground colors will be brighter. OK. Now we only need to do a little bit of work in the post code: protected void page_load (Object sender, eventargs e) {list
List = new list
(); Type T = typeof (color); // the header contains using system. drawing; // obtain the property propertyinfo [] properties = T. getproperties (bindingflags. static | bindingflags. public); Div div; // traverse the attribute foreach (propertyinfo P in properties) {// dynamically obtain the attribute color C; C = (color) T. invokemember (P. name, bindingflags. getproperty, null, typeof (color), null); DIV = new Div (c); list. add (DIV);} foreach (div item in list) {pncolors. cont Rols. Add (item) ;}} the code above is straightforward: first create a div list to save the color block to be created. Then, obtain the type instance of the color type. Then we use the getproperties () method and specify bindingflags to obtain all static public attributes. Then we traverse the attribute and use the invokemember () method to obtain the attribute value. Because an object type is returned, we need to forcibly convert it into a color type. Note that the bindingflags of invokemember is set to getproperty to get the property value. The fourth parameter is typeof (color), because the color attribute (such as darkgreen) is static, not for a specific instance. If it is an instance, you need to pass the type instance that calls this attribute. Finally, we create a div based on the color, add it to the list, traverse the list, and add it to the Panal control with the ID pncolors one by one. Now it's okay. If you open the page, you can see the effect similar to this: sorting the list page looks messy, because the list is roughly sorted by color name (except transparnet), we 'd better sort the list by color. As for list sorting, I have discussed in detail in the article "sort based on Business Objects". So here I will only show the implementation process, instead of the implementation process. This section has nothing to do with reflection. If you are familiar with sorting, you can skip this section. Add a radiobuttonlist control on the page and set autopostback to true. We need to sort by name or color value: sort by name color in the post code, add an enumeration as the basis for sorting: Public Enum sortby {name, // sort by name color // sort by dark color value} modify the DIV class and add the colorvalue field, this field represents the color value, and creates a nested colorcomparer, And the getcomparer: public class Div: htmlgenericcontrol {private int colorvalue; private string name; Public Div (color C ): base ("Div") // call the base class constructor to create a div {This. name = C. name; // color name this. colorvalue = // color value c. R * 256*256 + C. g * 256 + C. b; // set the text this. innerhtml = string. format ("{0}
RGB ({1}, {2}, {3}) ", name, C. r, C. g, C. b); int Total = C. R + C. G + C. b; If (total <= 255) // if the background color is too dark, the foreground color is changed to the clear color. This. style. add ("color", "# Eee"); // set the background color this. style. add ("background", String. format ("RGB ({0}, {1}, {2})", C. r, C. g, C. b);} // return a comparer () used to sort public static colorcomparer getcomparer (sortby sort) {return New colorcomparer (SORT );} // by default, public static colorcomparer getcomparer () {return getcomparer (sortby. name);} // nested type, used to sort public class colorcomparer: icomparer
{Private sortby sort; Public colorcomparer (sortby sort) {This. sort = sort;} // implement the icomparer interface. Based on the sort, determine what is based on the public int compare (Div X, div y) {If (sort = sortby. name) return string. compare (X. name, Y. name); else return X. colorvalue. compareto (Y. colorvalue) ;}}on the page_load event, we add a statement to obtain the current sorting basis (enumeration): sortby sort; If (! Ispostback) {sort = sortby. name;} else {sort = (sortby) enum. parse (typeof (sortby), rblsort. selectedvalue);} before outputting the list to the page, we call the sort method of the list: list. sort (div. getcomparer (SORT); // sort the list foreach (div item in list) {pncolors. controls. add (item) ;}now, all work is finished. Open the page again and you can see a screen similar to the following. We can sort the list by name or color value: the summary is divided into three parts. net: dynamically creates objects and calls object methods (attributes and fields ). First, we learned the two most common ways to dynamically create objects, and then discussed the use of type. invokemember () and methodinfo. the invoke () method is used to call the instance method and static method of the type. Finally, we use reflection to traverse the system. Drawing. Color Structure and output the color value.