The compatibility of dynamicmoduleutility objects in different. Net versions has been a strange problem for a hundred years: When ie encounters. NET Framework 4.5, we kindly remind Dudu and others that they intend to upgrade to. Net framewor.

Source: Internet
Author: User

The ASP. NET mvc3 framework contains a Microsoft. Web. InfrastructureProgramSet, which contains a dynamicmoduleutility object and its registermodule method. it is used to dynamically register the ihttpmodule in the program. generally, the module must be registered before the program starts. Therefore, the program that calls this method will generally mark the preapplicationstartmethod at the beginning, for example:

 Using  System;  Using  System. Web;  Using  Microsoft. Web. Infrastructure. dynamicmodulehelper; [Assembly: preapplicationstartmethod (  Typeof (Myappstart ), "  Start  " )]  Public   Class  Coolmodule: ihttpmodule {  //  Implementation not important  //  Imagine something cool here  }  Public   Static   Class  Myappstart {  Public   Static   Void Start () {dynamicmoduleutility. registermodule (  Typeof  (Coolmodule ));}} 

Therefore, if you directly write this call in the application_start method of the global. asax. CS file, it will report"ThisMethod cannot be called during the application'S pre-start initialization stage"Exception, as shown below:

However, the actual situation is more complicated than the above descriptions. I have a setCode, Developed at the same time in the company and at home. the registration code is directly written in the application_start method, and can be executed normally on the company's computer, that is, no error is reported, and all modules can be correctly registered! This leaves me puzzled. because the code is the same, the referenced class library has never changed, which makes me feel whether it is caused by the execution environment. my company's computer is 64-bit win7, installed vs08, 10, 12, the home is 32-bit win7, only installed 10. so I asked my colleagues to find a 64-bit computer and re-deploy and run it. An error is still reported. just as I had no clue, I suddenly remembered an article from Dudu.ArticleIt is a series of problems encountered after the garden is upgraded from. Net 4.0 to. Net 4.5. Will this be the reason? So I installed 2012 in my home machine and ran it again. Now the answer is clear: Compatibility Between. Net 4.0 and. net.

Before analyzing the problem in detail, you should have some preliminary knowledge.

1. CLR directory structure

After installing a specific version of. net, these dll will be deployed in three locations.

One is located in % WINDOWS % \ Microsoft. net \ framework, which is installed in a different directory than the data version. It is also called the CSC directory. by default, the CSC command is used to compile the program. The path to the Assembly referenced by the program is the root directory, CSC directory, and GAC directory of the program.

From. net 3.0 ,. net installer will deploy the same assembly at % Program Files % \ reference assemblies \ Microsoft \ framework. visual Studio will first reference the Assembly from here. therefore, when vs is used to compile a program, the search path of the Assembly referenced by the program is: the root directory of the program, the reference assemblies directory, and the GAC directory.

The last one is located in % WINDOWS % \ Microsoft. net \ Assembly, also known as the GAC directory, is essentially a directory with multi-level sub-directories. It can deploy different versions of DLL with the same file name at the same time, which is mainly used for program running. by default, when the program is running, the path of the Assembly referenced by the program is the root directory of the program and the GAC directory.

 

2.. Net version correspondence

We generally call. net2.0, 3.0, 3.5, 4.0, 4.5, or refers to the package version when it is released. It actually consists of the class library, compiler, and runtime, as shown in the following table:

. Net package version 1 1.1 2 3 3.5 4 4.5
Class Library version 1 1.1 2 3 3.5 4 4.5
C # compiler version 1 1.1 2 2 3 4 4
CLR version 1 1.1 2 2 2 4 4

3.. Net update policy

So far,. Net has used two update policies.

4.0 and earlier versions use side-by-side updates. all versions are stored in their respective directories. note that ,. net2.0, 3.0, and 3.5 are incremental updates, that is, they have not modified the existing assembly, but only added some features. for the public part, they use the same assembly.

4.5 uses in-place update, which overwrites all of its files to the 4.0 folder. That is to say, once updated to 4.5, it will certainly run in the 4.5 environment.

 

Next, let's take a closer look at why the registermodule method of the dynamicmoduleutility object reports an error in the 4.0 environment, and can be executed normally in the 4.5 environment.

First, The Decompilation Method

Public Static VoidRegistermodule (type moduletype ){If(Dynamicmodulereflectionutil. fx45registermoduledelegate! =Null) Dynamicmodulereflectionutil. fx45registermoduledelegate (moduletype );ElseLegacymoduleregistrar. registermodule (moduletype );}

We can also guess from the variable name that this method is actually different for different execution environments. Let's take a look at how dynamicmodulereflectionutil. fx45registermoduledelegate is generated.

 Public   Static   Readonly Action <type> fx45registermoduledelegate =Getfx45registermoduledelegate ();  Private   Static Action <type> Getfx45registermoduledelegate () {methodinfo Method = Typeof (Httpapplication). getmethod ( "  Registermodule  " , Bindingflags. Public | bindingflags. Static, Null , New Type [] { Typeof (Type )}, Null );  If (Method = Null ) Return   Null  ;  Return (Action <type>) Delegate. createdelegate ( Typeof (Action <type> ), Method );} 

In this way, the original program checks whether the httpapplication object has the registermodule method through reflection. If so, use this method directly.

Next we will view the httpapplication of. Net 4.0 and the httpapplication of 4.5 respectively.

4.0 is as follows

4.5 is as follows

Now I understand that two APIs are added in 4.5. Native supports dynamic registration of ihttpmodule and can be successfully registered in application_start () method.

Now let's look back at how the program handles the 4.0 environment. He calledRegistermodule method of the internal class of legacymoduleregistrar

 

Private Static ReadonlyDynamicmodulereflectionutil _ reflectionutil =Dynamicmodulereflectionutil. instance;Public Static VoidRegistermodule (type moduletype) {verifyparameters (moduletype );If(_ Reflectionutil! =Null){Lock(_ Lockobj) {_ reflectionutil. throwifpreappstartnotrunning. Invoke (); addmoduletoclassicpipeline (moduletype); addmoduletointegratedpipeline (moduletype );}}}

 

 

Haha, you can see from the name. It seems that if you do not register before the program runs, an exception will be thrown. Is that true? Watch againDynamicmodulereflectionutilClass

 [Compilergenerated]  Private Action <throwifpreappstartnotrunning> K _ backingfield;  Public  Action throwifpreappstartnotrunning {[compilergenerated]  Get  {  Return   This . <Throwifpreappstartnotrunning> K _ backingfield;} [compilergenerated] Private   Set  {  This . <Throwifpreappstartnotrunning> K _ backingfield = Value ;}}  Public   Static   Readonly Dynamicmodulereflectionutil instance = Getinstance ();  Private   Static  Dynamicmodulereflectionutil getinstance (){  Try  { If (Fx45registermoduledelegate! = Null ) Return   Null  ; Dynamicmodulereflectionutil util = New  Dynamicmodulereflectionutil (); methodinfo Method = Typeof (Buildmanager). getmethod ( "  Throwifpreappstartnotrunning  " , Bindingflags. nonpublic | bindingflags. Static, Null , Type. emptytypes, Null  ); Util. throwifpreappstartnotrunning = Commonreflectionutil. makedelegate <action> (Method); commonreflectionutil. Assert (util. throwifpreappstartnotrunning ! = Null  );......  Return  Util ;}  Catch  {  Return   Null  ;}} 

It setsThrowifpreappstartnotrunning is delegated to the throwifpreappstartnotrunning method of the buildmanager class.

 

 
Internal Static VoidThrowifpreappstartnotrunning (){If(Prestartinitstage! = Prestartinitstage. duringprestartinit)Throw NewInvalidoperationexception (Sr. getstring ("Method_can_only_be_called_during_pre_start_init"));}

 

Originally, if the program is not in the pre-running status, an exception will be thrown!

Now, the entire running logic is clear at a glance. if it is running in the 4.5 environment, this method will be delegated to the new API, which supports dynamic addition of ihttpmodule during runtime. if it is running in the 4.0 environment, it will check which stage is registered. if it is registered at runtime, an exception is thrown!

PS: It seems that the coverage update of 4.5 is not very stable. Why cannot we manually choose the running environment?

 

References:

A strange problem in a hundred years: When ie encounters. NET Framework 4.5

Kindly remind Dudu and other students who intend to upgrade to. NET Framework 4.5

What's new in ASP. NET 4.5 and Visual Studio 2012

Missing referenced assemblies folder for. Net 4.0

C: \ Program Files \ reference assemblies for assemblies to reference in your code

New Reference assemblies location

CLR: GAC directory Construction

. NET Framework Version Parsing

 

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.