Article content
As you know from the previous chapter, ASP. NET is running in httpruntime, but from the way the CLR enters httpruntime, it's probably not clear. This chapter is through in-depth analysis. Net4 's source code to show the important steps. Please look first:
First, the CLR loads a very important class appmanagerappdomainfactory when it initializes, what does this class do? First, this class inherits the Iappmanagerappdomainfactory interface, which is a create method that is available for COM calls, with the following code:
[ComImport, Guid ("02998279-7175-4d59-aa5a-fb8e44d4ca9d"), System.Runtime.InteropServices.InterfaceTypeAttribute ( System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)] Public InterfaceIappmanagerappdomainfactory {#if! Feature_pal//Feature_pal does not enable COM [return: MarshalAs (unmanagedtype.interface)]#else // ! Feature_palObject Create (String appId, String appPath);#endif // ! Feature_palObject Create ([In, MarshalAs (UNMANAGEDTYPE.BSTR)] String appId, [In, MarshalAs (unmanaged TYPE.BSTR)] [String AppPath]; voidStop (); }
Let's take a closer look at how this appmanagerappdomainfactory implements this interface, first the class in the default constructor, obtains a Applicationmanager instance for use in the Create method. The code is as follows:
[SecurityPermission (SecurityAction.Demand, unrestricted=true)] Public appmanagerappdomainfactory () { = Applicationmanager.getapplicationmanager ();
Back to the Create method that implements the interface, let's look at the most important 3 lines of code:
Isapiapplicationhost AppHost =NewIsapiapplicationhost (AppId, AppPath,false /*Validatephysicalpath*/); Isapiruntime Isapiruntime= (isapiruntime) _appmanager.createobjectinternal (AppId,typeof(Isapiruntime), AppHost,false /*failifexists*/,NULL /*hostingparameters*/); isapiruntime.startprocessing ();
The main function of code is to get an instance of Isapiruntime by Applicationmanager createobjectinternal A series of operations, and then let unmanaged code invoke it. So the createobjectinternal approach plays a vital role here: Create an AppDomain, create a hostingenvironment, and more.
First, look at the Appmanagerappdomainfactory constructor, which calls the Applicationmanager. The Getapplicationmanager () method is a singleton implementation with the following code:
Public StaticApplicationmanager Getapplicationmanager () {if(_theappmanager = =NULL) { Lock(_applicationmanagerstaticlock) {if(_theappmanager = =NULL) { if(hostingenvironment.ishosted) _theappmanager=Hostingenvironment.getapplicationmanager (); if(_theappmanager = =NULL) _theappmanager=NewApplicationmanager (); } } } return_theappmanager;}
From the code point of view, you may be a little puzzled why the Hostingenvironment property ishosted to True will call its static method Getapplicationmanager () to get the instance of Applicationmanager, This is because Applicationmanager automatically passes this to the Hostingenvironment object instance (which is explained later) when the Hostingenvironment object is created and initialized in subsequent steps.
Looking back at the Createobjectinternal method of the Applicationmanager instance, some of the code is as follows:
//Get hosting environmenthostingenvironment Env=getappdomainwithhostingenvironment (AppId, AppHost, hostingparameters);//Create the managed object in the Worker app domain//When marshaling Type, the AppDomain must has FileIoPermission to the assembly, which are not//Always the case, so we marshal the assembly qualified name insteadObjectHandle H=Env. Createwellknownobjectinstance (type. AssemblyQualifiedName, failifexists);return(H! =NULL) ? H.unwrap () asIRegisteredObject:NULL;
We can see from the code that we first get an instance of Hostingenvironment, and then return the instance of Isapiruntime required by the Createwellknownobjectinstance method of the example. Then we should be able to think of getappdomainwithhostingenvironment has 2 functions, one is to get the AppDomain first, and the other is to get hostingenvironment instances, to see if the code as we guessed the result, First look at the code:
Privatehostingenvironment getappdomainwithhostingenvironment (String appId, Iapplicationhost appHost, Hostingenvironmentparameters hostingparameters) {lockableappdomaincontext AC=Getlockableappdomaincontext (appId); Lock(AC) {hostingenvironment env=AC. hostenv; if(Env! =NULL) { Try{env. Isunloaded (); } Catch(appdomainunloadedexception) {env=NULL; } } if(env = =NULL) {env=createappdomainwithhostingenvironmentandreporterrors (AppId, AppHost, hostingparameters); Ac. Hostenv=env; Interlocked.Increment (ref_accessiblehostingenvcount); } returnenv; } }
The code tells us that we will first check if there is an existing adddomain and the corresponding hostingenvironment instance, and if there is a return, it will create a new one. Through the call, finally came to a private method createappdomainwithhostingenvironment, in this 300-line private method, there is something we have been puzzled about for a long time.
First there will be about the level of trust code, such as running on FullTrust or middletrust, there will be the corresponding processing code, because the focus of our code analysis is not here, so the specific code is not detailed, to see what we need to know the code snippet:
//Create the app domainAppDomain AppDomain=NULL;//A lot of code is omitted hereif(Islegacycas) {AppDomain=Appdomain.createdomain (Domainid,#ifFeature_pal//Feature_pal:hack to avoid non-supported hosting features NULL,#else //Feature_palgetdefaultdomainidentity (),#endif //Feature_palsetup);}Else{AppDomain=Appdomain.createdomain (Domainid,#ifFeature_pal//Feature_pal:hack to avoid non-supported hosting features NULL,#else //Feature_palgetdefaultdomainidentity (),#endif //Feature_palSetup, PermissionSet, fullTrustAssemblies/*fully trusted assemblies list:null means only trust GAC assemblies*/);}
Through the code can be seen, this is the legend of the creation of the AppDomain, all the following things such as HttpRuntime, HttpContext are based on this AppDomain, which is why HttpContext can not be shared in multiple sites, And can safely exist in the AppDomain.
Keep looking down, there are several lines of code after creating the AppDomain's code:
Type HostType =typeof(hostingenvironment); String Module=HostType.Module.Assembly.FullName; String TypeName=Hosttype.fullname;objecthandle H=NULL;//A lot of code is omitted hereh=activator.createinstance (AppDomain, module, typeName);//A lot of code is omitted herehostingenvironment Env= (H! =NULL) ? H.unwrap () asHostingenvironment:NULL;//A lot of code is omitted hereif(Appdomainstartupconfigurationexception = =NULL) {env. Initialize ( This, AppHost, Configmappathfactory, Hostingparameters, PolicyLevel); } Else{env. Initialize ( This, AppHost, Configmappathfactory, Hostingparameters, PolicyLevel, appdomainstartupconfigurationexception);}returnEnv
This is where the hostingenvironment instance is created, and after the instance is created, the Initialize method is called to initialize, and then the object instance is returned (note that the first parameter of the method is this, That is, the Applicationmanager instance itself, explains the above-mentioned why I can pass the static method of Hostingenvironment Getapplicationmanager () To get the Applicationmanager instance).
With this code, we can simply know how to get the Isapiruntime instance and prepare for entering the httpruntime. However, I'm still curious about what Hostingenvironment's initialize initialization method actually does, okay, let's take a look.
OK, you've got a line of important code:
// Initiaze http-independent features httpruntime.initializehostingfeatures (Hostingflags, PolicyLevel, appdomaincreationexception);
The code goes into the static method of httpruntime, and then calls the Hostingint method to do some initialization work, with one line of code that we need to know, as follows:
// Initialize the build manager Buildmanager.initializebuildmanager ();
The BuildManager Initializebuildmanager method, which calls its own Initialize method, initializes additional work, including compiling all of the. NET source code in the App_Code directory. By the above series of introductions we know that in an AppDomain there is only one hostringenvironment, so this buildmanager initialize is only executed once, To ensure that the compilation is not a problem (the source of the comment is also said OH).
In addition, in the Hostinginit method, there is a very special code in the catch when the initialization fails:
true;
This is to say that when creating a hostingenvironment failure, the httpruntime hostinginitfailed is assigned true. The concept of Preapplicationstartmethodattribute discussed in the later chapters and the entrance to the Webactivator are related to this value and are not discussed now, but later chapters are fine.
Well, back to Appmanagerappdomainfactory's create method, after getting an instance of Isapiruntime and running the Startprocessing method, a ObjectHandle object is returned to the unmanaged code, This includes an example of Isapiruntime, with the following code:
return New ObjectHandle (Isapiruntime);
What does unmanaged code do after accepting the ObjectHandle object? We also look at the continuation of the next article.
Synchronization and recommendations
This article has been synchronized to the directory index: Thelittle Thing before MVC series
MVC before the point of the series of articles, including the original, translation, reprint and other types of articles, if it is useful to you, please recommend supporting a, to the power of the uncle writing.