People who have used reflection know that invoking a method is simple, but how do you prepare an incoming parameter for an "unsigned" method?
To answer this question, please follow the getactioncallparameters implementation process:
private static object[] Getactioncallparameters (HttpContext context, actiondescription action) {if (action. Parameters = = NULL | | Action. Parameters.length = = 0) return null; object[] Parameters = new Object[action. Parameters.length]; for (int i = 0; I < action. Parameters.length; i++) {ParameterInfo p = action. Parameters[i]; if (p.isout) continue; if (P.parametertype = = typeof (NameValueCollection)) {if (string. Compare (P.name, "Form", stringcomparison.ordinalignorecase) = = 0) Parameters[i] = context. Request.Form; else if (string. Compare (P.name, "QueryString", stringcomparison.ordinalignorecase) = = 0) Parameters[i] = context. Request.QueryString; else if (string. Compare (P.name, "Headers", stringcomparison.ordinalignorecase) = = 0) Parameters[i] = context. Request.headers; else if (string. Compare (P.name, "ServerVariables", stringcomparison.ordinalIgnoreCase) = = 0) Parameters[i] = context. Request.ServerVariables; } else{Type Paramtertype = P.parametertype.getrealtype (); If the argument is a simple type, it is read directly from the HttpRequest and assigned the value if (Paramtertype.issimpletype ()) {Object val = modelhelper. Getvaluebykeyandtypefrommrequest (context. Request, p.name, paramtertype, NULL); if (val! = null) parameters[i] = val; } else {//custom type. Create the instance first, and then assign values to all the members. Note: Custom types for nested types are not supported here. Object item = Activator.CreateInstance (Paramtertype); Modelhelper.fillmodel (context. Request, item, p.name); Parameters[i] = Item; }}} return parameters;}
To understand this code also starts with the "procedure for finding an action" in the previous section, at which point you can get a description of the action, which is represented as a actiondescription type within the framework:
Internal sealed class actiondescription:basedescription{public controllerdescription Pagecontroller; Leave public MethodInfo MethodInfo {get; private set for pageaction;} Public Actionattribute Attr {get; private set;} Public parameterinfo[] Parameters {get; private set;} public bool Hasreturn {get; private set;} Public Actiondescription (MethodInfo m, Actionattribute atrr): Base (m) {this . MethodInfo = m; This. Attr = ATRR; This. Parameters = M.getparameters (); This. Hasreturn = m.returntype! = Reflectionhelper.voidtype; }}
In the third line of code of the constructor, I can get all the parameters of this method.
Then I can iterate over the definition of each parameter in the Getactioncallparameters method and assign a value to them.
This code also explains the previous reason for supporting only 4 types of NameValueCollection collections.
Note that when I get the type of each parameter, I use the following statement:
Type Paramtertype = P.parametertype.getrealtype ();
In fact, ParameterType has already reflected the type of the parameter, why not use it directly?
Answer: Because of the "can be vague" reason. We need special treatment for this type.
For example, if a parameter is declared like this: int? Id
So, even if you include an ID in QueryString, I can't go straight to int? With this type, you must get the "actual type" of it.
Getrealtype () is an extension method that specifically accomplishes this function:
<summary>///gets an actual type (excluding the effects of the nullable type). For example: int? Finally will get int///</summary>///<param name= "type" ></param>///<returns></returns>public Static type Getrealtype (this type type) { if (type). Isgenerictype) return Nullable.getunderlyingtype (type)?? type; else return type;}
If the type of a parameter is a custom type, the framework creates an instance (calling the parameterless constructor) and assigns a value to its property, field.
Note: For custom types, be sure to provide an argument-free constructor.
The code for populating a data member for an instance of a custom type is as follows:
Internal static class modelhelper{public static readonly bool Isdebugmode; Static Modelhelper () {compilationsection configsection = configurationmanager.getsection ("s Ystem.web/compilation ") as compilationsection; if (configsection! = null) Isdebugmode = Configsection.debug; }///<summary>//fill in a data entity according to HttpRequest. Data entities of nested types are not supported here, and data members are required to be simple data types. </summary>//<param name= "Request" ></param>//<param name= "model" ></param> public static void Fillmodel (HttpRequest request, object model, string paramname) {Modeldescripton Descripton = Reflectionhelper.getmodeldescripton (model. GetType ()); Object val = null; foreach (DataMember field in Descripton. Fields) {//This implementation does not support data entities of nested types. If there is a need for this, you can change this to a recursive nested call. val = getvaluebykeyandtypefrommrequest (Request, field. Name, Field. Type.getrealtype (), paramname); if (val! = null) field. SetValue (model, Val); }}///<summary> read an HTTP parameter value. Here only read QueryString and form///</summary>//<param name= "Request" ></param>//<param name= "Ke Y "></param>///<returns></returns> public static string Gethttpvalue (HttpRequest request, Stri ng key) {string val = Request. Querystring[key]; if (val = = null) val = Request. Form[key]; return Val; public static object Getvaluebykeyandtypefrommrequest (HttpRequest request, string key, Ty PE type, string paramname) {//Does not support complex type if (type. Issimpletype () = = false) return null; String val = gethttpvalue (request, key); if (val = = null) {//try again. There may be more than one custom type, and the form element is prefixed with the variable name. if (string. IsNullOrEmpty (paramname) = = False) {val = GethttpvaLue (Request, ParamName + "." + key); } if (val = = null) return null; } return Safechangetype (val. Trim (), type); The public static object Safechangetype (string value, Type conversiontype) {if (Conversiontype = = typeof (Strin g)) return value; if (value = = NULL | | value. Length = = 0)//An empty string cannot be converted at all, so it returns null return null directly; try {//For simplicity, call methods in the. NET Framework directly. If the conversion fails, an exception is thrown. return Convert.changetype (value, conversiontype); } catch {if (isdebugmode) throw; Throw exception in Debug mode else return null; Ignore exception in release mode (prevents malicious user from wrong Input)}}}
Before loading data to a custom data type instance, you need to know what properties and fields the instance object has, and the code for this process is as follows:
<summary>///returns the description information for an entity type (all properties and fields). </summary>///<param name= "type" ></param>///<returns></returns>public static Modeldescripton Getmodeldescripton (Type type) { if (type = null) throw new ArgumentNullException ("type"); String key = Type. FullName; Modeldescripton mm = (Modeldescripton) S_modeltable[key]; if (mm = = null) { list<datamember> List = new list<datamember> (); (from P in type.) GetProperties (BindingFlags.Instance | BindingFlags.Public) Select New Propertymember (P)). ToList (). ForEach (x=>list. ADD (x)); (from F in type.) GetFields (BindingFlags.Instance | BindingFlags.Public) Select New Fieldmember (f)). ToList (). ForEach (x = list. ADD (x)); MM = new Modeldescripton {fields = list. ToArray ()}; S_modeltable[key] = mm; } return mm;}
After getting all the properties of a type and the description of the field, it is possible to querystring,form to read the required data by the name of the data member in a circular way.
"Recommended"
1. Special recommendation : "PHP Programmer Toolkit" V0.1 version download
2. asp free Video Tutorial
3. an entry-level. NET MVC Instance
4. MYMVC The process of finding action in the box
5. the. NET MYMVC Framework performs an action-detailed procedure
6. the. NET MYMVC Framework processes the return value tutorial