Controllerdescriptor's understanding

Source: Internet
Author: User

The Controllerdescriptor class mainly contains the parsing of the control metadata in ASP. Controllerdescriptor class is often encountered in the model binding and data processing of MVC.

The Controllerdescriptor class is an abstract class in ASP. NET MVC source code. It inherits the Iuniquelyidentifiable interface (which contains only the interface of the UniqueID attribute) and the ICustomAttributeProvider interface (gets the attribute applied on the corresponding parameter);

There are 3 main properties of the Controllerdescriptor class

When implemented in a derived class, gets the unique ID of the controller descriptor by using lazy initialization. TD data-th= "description" >
& nbsp;
controllername < Span id= "MT4" class= "sentence" data-guid= "7c180b0805ea3194bad4c1b0369ca83d" data-source= "" > Gets the name of the controller.
controllertype Get the class of the controller Type.
uniqueid

The Controllername attribute is obtained by controllertype.name and the controller suffix is removed;

The UniqueID property is primarily to determine uniqueness, through Controllername,controllertype in the Controllerdescriptor class, The type of Controllerdescriptor itself is created (through the source can be found mainly by the length of the string + string has been [{0}]{1} format superimposed together, Specific implementation can refer to the source code in the Descriptorutil.createuniqueid method);

The Controllerdescriptor class contains an abstract method of important methods Findaction, the purpose of which is to use the specified name and controller context to find the action method.

Reflectedcontrollerdescriptor

Reflectedcontrollerdescriptor class is the implementation class of inheriting controllerdescriptor in the MVC framework; The constructor of the Reflectedcontrollerdescriptor class receives the type of a controller, and in the constructor the component is a Actionmethodselector read-only class;

The Reflectedcontrollerdescriptor class covers the getcanonicalactions,getcustomattributes of the abstract base class Controllerdescriptor, Getfilterattributes,isdefined,findaction method;

The function of the IsDefined method is to return a Boolean value that defines whether one or more instances of a custom attribute type are defined for this member; the bool IsDefined of the MemberInfo class is called directly inside the function (type attributetype, bool Inherit); isdefined can be used to determine whether there is an attribute value acting on the controller;

An array of all the custom attributes is obtained when the GetCustomAttributes method is used, and the GetCustomAttributes method can be used to obtain these properties when there is an attribute acting on the controller.

Both the IsDefined method and the GetCustomAttributes method are derived from the ICustomAttributeProvider interface;

The Getfilterattributes method realizes all the characteristics of the FilterAttribute interface. The inside of the function is called the GetCustomAttributes method (the GetCustomAttributes method parameter type is typeof (FilterAttribute));

The purpose of the Getcanonicalactions method is to return a list of all actions within the controller, with a return value of actiondescriptor[];

The Findaction method is the most important method in Controllerdescriptor, which filters out the corresponding action by ControllerContext (Controller context) and ActionName. return to Actiondescriptor; inside this function first through _ The Findactionmethod method of the selector (type Actionmethodselector) class gets the matching method metadata information (the return value is MethodInfo). Then call the constructor of the Reflectedactiondescriptor class (base class: Actiondescriptor);

Actionmethodselectorbase

The Actionmethodselector class inherits the Actionmethodselectorbase base class, and the main function of this class is action filtering;

The Actionmethodselectorbase class contains Controllertype, (type: methodinfo[]) Actionmethods (all action methods),

(Type:hashset<methodinfo>) Standardroutemethods (method of direct routing),

(type: methodinfo[]) Aliasedmethods (the name of the action in the MVC framework can be renamed by the attribute Actionnameselectorattributes, so this property is the method information that holds the alias),

(Type: ilookup<string, methodinfo>) Nonaliasedmethods (method information for an action that stores no alias information, the name of the key action);

All action methods are also cached in the Actionmethodselectorbase class, stored in the Standardroutecache property (private), The type of the Standardroutecache property is the Standardrouteactionmethodcache class, which is simple for the Standardrouteactionmethodcache class and has 2 properties. One is the ilookup<string that stores the method information without alias information, methodinfo> Nonaliasedmethods and methodinfo[] Aliasedmethods with alias information; The logic of creating the cache in the Createstandardroutecache method is also simple, first filtering out the methods in the Standardroutemethods list that contain Actionnameselectorattribute, Then, a collection of methods with no alias information is obtained in the difference set with Standardroutemethods;

The Actionmethodselector class is created in the constructor of the Reflectedcontrollerdescriptor class, and Actionmethodselector calls the initialize of the base class in the constructor to complete the initialization. All public methods in the Controllertype class are first acquired during initialization, and all action methods are filtered out by the Isvalidactionmethod method in the Actionmethodselector class; and written to the Standardroutemethods attribute; The filter method for action can be seen by code

    protected Override BOOL Isvalidactionmethod (MethodInfo MethodInfo)    {       return ! (Methodinfo.isspecialname | | methodinfo.getbasedefinition (). Declaringtype.isassignablefrom (typeof(Controller)));    

When the Findaction method is used, the Findactionmethod method of the base class is called directly, and in this method the alias method in the cache is selected first, because the Alias method list is an array, and each item is traversed Gets the list of subclasses of the Actionnameselectorattribute class that inherit from each item, since Actionnameselectorattribute is an abstract class that contains the bool IsValidName ( ControllerContext ControllerContext, String actionname, MethodInfo MethodInfo) abstract method, when the alias matching is called IsValidName to verify;

       protected Static BOOLIsmatchingaliasedmethod (MethodInfo method, ControllerContext ControllerContext,stringactionname) {            //return if aliased method is opting on to this request//to opt in, all attributes defined on the method must return Truereadonlycollection<actionnameselectorattribute> attributes =Reflectedattributecache.getactionnameselectorattributes (method); //Caching count is faster for ReadOnlyCollection          intAttributecount =attributes.            Count; //performance sensitive, so avoid foreach           for(inti =0; i < Attributecount; i++)          {             if(!Attributes[i]. IsValidName (ControllerContext, ActionName, method)) {return false; }            }         return true; }

When all alias lists are traversed, a filter with no Alias method list is made, because the list of non-aliased methods in the cache is stored in the format ilookup<string, methodinfo> format, so directly through key (action name) to obtain;

When all the data in the cache is found, a collection of method metadata is obtained, and then the final filter is made after the call to the Runselectionfilters method, and when the filter is complete, if there are no elements in the list, the current element is returned when it is an element, and when there are multiple elements, It will throw a ambiguousmatchexception error;

The Runselectionfilters method mainly filters the results,

The first is to filter based on the Actionmethodselectorattribute feature, first to get a list of the Actionmethodselectorattribute properties of the method, If the method does not have this methodselectionattribute, the method should be removed if there is already a method in the method list that marks the Actionmethodselectorattribute attribute.

Actionmethodselectorattribute contains an abstract method bool Isvalidforrequest (ControllerContext ControllerContext, MethodInfo MethodInfo);

The second is to call Isvalidmethodselector, this method is also called Actionmethodselectorattribute Isvalidforrequest method;

    protected Static voidRunselectionfilters (ControllerContext ControllerContext, list<methodinfo>Methodinfos) {            //Filter Depending on the selection attribute. //Methods with valid selection attributes override all others. //Methods with one or more invalid selection attributes is removed.            BOOLHasvalidselectionattributes =false; //loop backwards for fastest removal             for(inti = Methodinfos.count-1; I >=0; i--) {MethodInfo MethodInfo=Methodinfos[i]; ReadOnlyCollection<ActionMethodSelectorAttribute> attrs =reflectedattributecache.getactionmethodselectorattributescollection (MethodInfo); if(Attrs. Count = =0)                {                    //Case 1:this method does not having a methodselectionattribute                    if(hasvalidselectionattributes) {//If there is already method with a valid selection attribute, remove method without onemethodinfos.removeat (i); }                }                Else if(Isvalidmethodselector (Attrs, ControllerContext, MethodInfo)) {//Case 2:this method have methodselectionattributes that is all valid//If a matching action method had a selection attribute, consider it more specific than a matching action method //without a selection attribute                    if(!hasvalidselectionattributes) {                        //When the first selection attribute are discovered, remove any items later in the list without selection attributes                        if(i +1<methodinfos.count) {Methodinfos.removefrom (i+1); } hasvalidselectionattributes=true; }                }                Else                {                    //Case 3:this method have a method selection attribute but it 's not valid//Remove the method since it is opting out of this requestmethodinfos.removeat (i); }            }        } protected Static BOOLIsvalidmethodselector (readonlycollection<actionmethodselectorattribute>attributes, ControllerContext ControllerContext, MethodInfo method) {            intAttributecount =attributes.            Count; Contract.assert (Attributecount>0);  for(inti =0; i < Attributecount; i++)            {                if(!Attributes[i]. Isvalidforrequest (ControllerContext, method)) {return false; }            }            return true; }
View Code

Controllerdescriptor's understanding

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.