tutorial on how the. NET MYMVC Framework assigns values to methods

Source: Internet
Author: User
Tags servervariables
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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.