Asp.net MVC source code analysis-action execution

Source: Internet
Author: User

Next, I will go to the Asp.net MVC source code analysis-action defaultmodelbinder. We have obtained the action parameters. We have the previous content. We know the invokeactionmethod METHOD OF THE controlleractioninvoker class when calling the action.

Protected virtual actionresult invokeactionmethod (controllercontext, actiondescriptor, idictionary <string, Object> parameters ){
Object returnvalue = actiondescriptor. Execute (controllercontext, parameters );
Actionresult result = createactionresult (controllercontext, actiondescriptor, returnvalue );
Return result;
}

We now know that actiondescriptor is an instance of the reflectedactiondescriptor class,

The implementation of the execute method of reflectedactiondescriptor is roughly as follows:

Public override object execute (controllercontext, idictionary <string, Object> parameters ){
Parameterinfo [] parameterinfos = methodinfo. getparameters ();
VaR rawparametervalues = from parameterinfo in parameterinfos
Select extractparameterfromdictionary (parameterinfo, parameters, methodinfo );
Object [] parametersarray = rawparametervalues. toarray ();
Actionmethoddispatcher dispatcher = dispatchercache. getdispatcher (methodinfo );
Object actionreturnvalue = dispatcher. Execute (controllercontext. Controller, parametersarray );
Return actionreturnvalue;
}

Parameterinfo [] parameterinfos = methodinfo. getparameters (); it is nothing to say about getting the parameter set of action. You should know what parameters is in the method parameter. A parameter named key with the parameter of action, the value is a dictionary combination of values.

VaR rawparametervalues = from parameterinfo in parameterinfos
Select extractparameterfromdictionary (parameterinfo, parameters, methodinfo );
Object [] parametersarray = rawparametervalues. toarray ();

The two statements form an array of parameter values in parameters according to the order of parameters in the action. The extractparameterfromdictionary method is to check the data validity in parameters. It mainly checks whether parameters contains parameterinfo. name. If no exception is thrown, check whether it is null. If it is null, check whether the parameter is allowed to be null. If it is not allowed, throw an exception, if not null, check whether the value is an instance of the parameter type.

Actionmethoddispatchercache is implemented as follows:

Internal sealed class actionmethoddispatchercache: readerwritercache <methodinfo, actionmethoddispatcher> {
Public actionmethoddispatchercache (){}
Public actionmethoddispatcher getdispatcher (methodinfo ){
ReturnFetchorcreateitem(Methodinfo, () => NewActionmethoddispatcher(Methodinfo ));
}
}

We will not mention the fetchorcreateitem here. It was said in the actionmethoddispatchercache class. Getdispatcher actually returnsActionmethoddispatcherClass.

Public actionmethoddispatcher (methodinfo ){
_ Executor = getexecutor (methodinfo );
Methodinfo = methodinfo;
}

the getexecutor Code is as follows:

Private Static actionexecutor getexecutor (methodinfo) {// parameters to executor parameterexpression controllerparameter = expression. parameter (typeof (controllerbase), "controller"); parameterexpression parametersparameter = expression. parameter (typeof (object []), "Parameters"); // build parameter list <expression> parameters = new list <expression> (); parameterinfo [] paraminfos = met Hodinfo. getparameters (); For (INT I = 0; I <paraminfos. length; I ++) {parameterinfo paraminfo = paraminfos [I]; binaryexpression valueobj = expression. arrayindex (parametersparameter, expression. constant (I); unaryexpression valuecast = expression. convert (valueobj, paraminfo. parametertype); // valuecast is "(Ti) parameters [I]" parameters. add (valuecast);} // call method unaryexpression instancecast = (! Methodinfo. isstatic )? Expression. convert (controllerparameter, methodinfo. reflectedtype): NULL; methodcallexpression methodcall = expression. call (instancecast, methodinfo, parameters); // methodcall is "(tcontroller) controller) method (t0) parameters [0], (T1) parameters [1],...) "// create function if (methodcall. type = typeof (void) {expression <voidactionexecutor> Lambda = expression. lambda <voidactionexecutor> (methodcall, controllerparameter, parametersparameter); voidactionexecutor voidexecutor = lambda. compile (); Return wrapvoidaction (voidexecutor);} else {// must coerce methodcall to match actionexecutor signature unaryexpression castmethodcall = expression. convert (methodcall, typeof (object); expression <actionexecutor> Lambda = expression. lambda <actionexecutor> (castmethodcall, controllerparameter, parametersparameter); Return lambda. compile ();}}

In fact, this code is quite understandable.,Is the call to generate an action method using the expression tree. The Code returns an actionexecutor delegate. In this getexecutor method, it takes a lot of time.
Lambda. Compile (), have you ever wondered why to use the expression tree instead of calling the methodinfo invoke method ?, The invoke caller is actually very slow. The most important thing is that the invocation process cannot be cached. However, although it takes a little longer to compile an expression into a delegate, however, there is an actionmethoddispatchercache to ensure that the delegate instance required for each action call only needs to be compiled once. The performance of calling the same action expression multiple times is much higher than that of the invoke method.. We can see that Microsoft has done a good job of caching in mvc3.

Object actionreturnvalue = dispatcher. Execute (controllercontext. Controller, parametersarray); this statement calls the _ executor delegate, that is, the actual execution of the Action method. actionreturnvalue is the return value of the action. The default value is an actionresult.

Now let's take a look at actionresult result = createactionresult (controllercontext, actiondescriptor, returnvalue); this method:

Protected virtual actionresult createactionresult (controllercontext, actiondescriptor, object actionreturnvalue ){
If (actionreturnvalue = NULL ){
Return new emptyresult ();
}

Actionresult = (actionreturnvalue as actionresult )??
New contentresult {content = convert. tostring (actionreturnvalue, cultureinfo. invariantculture )};
Return actionresult;
}

Actionresult = (actionreturnvalue as actionresult )?? New contentresult {content = convert. tostring (actionreturnvalue, cultureinfo. invariantculture )};YesCheck whether an actionresult is returned by an action. If not, construct a contentresult and return it. I wonder if throw is better if action does not return actionresult.

For example, our action is as follows:

Public class homecontroller: Controller
{
Public object index () {return New {name = "majiang "};}
}

Returned results:

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.