Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   How the Runtime Resolves Type References

At the beginning of Chapter 2, we saw the following source code.

 

public sealed class Program { public static void Main() {

System.Console.WriteLine("Hi");

}

}

 

This code is compiled and built into an assembly, say Program.exe. When you run this application, the CLR loads and initializes. Then the CLR reads the assembly’s CLR header, looking for the Method- DefToken that identifies the application’s entry point method (Main). From the MethodDef metadata table, the offset within the file for the method’s IL code is located and JIT-compiled into native code, which includes having the code verified for type safety. The native code then starts executing. Follow- ing is the IL code for the Main method. To obtain this output, I ran ILDasm.exe, chose the View menu’s Show Bytes menu item, and then double-clicked the Main method in the tree view.

 

.method public hidebysig static void Main() cil managed

// SIG: 00 00 01

{

.entrypoint

// Method begins at RVA 0x2050

// Code size 11 (0xb)

.maxstack 8

IL_0000: /* 72 | (70)000001 */

ldstr "Hi"

IL_0005: /* 28 | (0A)000003 */

call void [mscorlib]System.Console::WriteLine(string)

IL_000a: /* 2A | */ ret

} // end of method Program::Main

 

When JIT-compiling this code, the CLR detects all references to types and members and loads their defining assemblies (if not already loaded). As you can see, the preceding IL code has a refer- ence to System.Console.WriteLine. Specifically, the IL call instruction references metadata token 0A000003. This token identifies entry 3 in the MemberRef metadata table (table 0A). The CLR looks up this MemberRef entry and sees that one of its fields refers to an entry in a TypeRef table (the System.Console type). From the TypeRef entry, the CLR is directed to an AssemblyRef entry: “mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”. At this point, the CLR knows which assembly it needs. Now the CLR must locate the assembly in order to load it.


When resolving a referenced type, the CLR can find the type in one of three places:

 

Same fileAccess to a type that is in the same file is determined at compile time (sometimes

referred to as early bound). The type is loaded out of the file directly, and execution continues.

 

Different file, same assemblyThe runtime ensures that the file being referenced is, in fact, in the assembly’s ModuleRef table of the current assembly’s manifest. The runtime then looks in the directory where the assembly’s manifest file was loaded. The file is loaded, its hash value is checked to ensure the file’s integrity, the type’s member is found, and execution continues.

Different file, different assemblyWhen a referenced type is in a different assembly’s file, the runtime loads the file that contains the referenced assembly’s manifest. If this file doesn’t contain the type, the appropriate file is loaded. The type’s member is found, and execution continues.



       
   
 
 

 

If any errors occur while resolving a type reference—file can’t be found, file can’t be loaded, hash

mismatch, and so on—an appropriate exception is thrown.

       
   
 
 

 

In the previous example, the CLR determines that System.Console is implemented in a different assembly than the caller. The CLR must search for the assembly and load the PE file that contains the assembly’s manifest. The manifest is then scanned to determine the PE file that implements the type. If the manifest file contains the referenced type, all is well. If the type is in another of the assembly’s files, the CLR loads the other file and scans its metadata to locate the type. The CLR then creates its internal data structures to represent the type, and the JIT compiler completes the compilation for the Main method. Finally, the Main method can start executing.


Figure 3-2 illustrates how type binding occurs.

 
 

 

Note: If any operation fails, an appropriate exception is thrown.

FIGURE 3-2Flowchart showing how, given IL code that refers to a method or type, the CLR uses metadata to

locate the proper assembly file that defines a type.

       
   
 
 


There is one more twist to this story: to the CLR, all assemblies are identified by name, version, culture, and public key. However, the GAC identifies assemblies by using name, version, culture, public key, and CPU architecture. When searching the GAC for an assembly, the CLR figures out what type

of process the application is currently running in: 32-bit x86 (possibly using the WoW64 technology), 64-bit x64, or 32-bit ARM. Then, when searching the GAC for an assembly, the CLR first searches for a CPU architecture–specific version of the assembly. If it does not find a matching assembly, it then searches for a CPU-agnostic version of the assembly.

In this section, you saw how the CLR locates an assembly when using a default policy. However, an administrator or the publisher of an assembly can override the default policy. In the next two sections, I’ll describe how to alter the CLR’s default binding policy.

 

NoteThe CLR supports the ability to move a type (class, structure, enum, interface, or delegate) from one assembly to another. For example, in the .NET Framework 3.5, the

System.TimeZoneInfo class is defined in the System.Core.dll assembly. But in the .NET Framework 4, Microsoft moved this class to the MSCorLib.dll assembly. Normally, moving a type from one assembly to another would break applications. However, the CLR offers a System.Runtime.CompilerServices.TypeForwardedToAttribute attribute, which can be applied to the original assembly (such as System.Core.dll). The parameter that you pass to this attribute’s constructor is of type System.Type and it indicates the new type (that is now defined in MSCorLib.dll) that applications should now use. The CLR’s binder uses this information. Because the TypeForwardedToAttribute’s constructor takes a Type, the as- sembly containing this attribute will be dependent on the new assembly defining the type.

If you take advantage of this feature, then you should also apply the attribute System.Runtime.CompilerServices.TypeForwardedFromAttribute to the type in the new assembly and pass to this attribute’s constructor a string with the full name of the assembly that used to define the type. This attribute typically is used for tools, utilities, and serialization. Because the TypeForwardedFromAttribute’s constructor takes a String, the assembly containing this attribute is not dependent on the as- sembly that used to define the type.

 

 
 

Advanced Administrative Control (Configuration)

In the section “Simple Administrative Control (Configuration)” in Chapter 2, I gave a brief introduc- tion to how an administrator can affect the way the CLR searches and binds to assemblies. In that section, I demonstrated how a referenced assembly’s files can be moved to a subdirectory of the application’s base directory and how the CLR uses the application’s XML configuration file to locate the moved files.


Having discussed only the probing element’s privatePath attribute in Chapter 2, I’m going to

discuss the other XML configuration file elements in this section. Following is an XML configuration file.

 

<?xml version="1.0"?>

<configuration>

<runtime>

<assemblyBinding xmlns="urn:schemas­microsoft­com:asm.v1">

<probing privatePath="AuxFiles;bin\subdir" />

 

<dependentAssembly>

 

<assemblyIdentity name="SomeClassLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="neutral"/>

 

<bindingRedirect

oldVersion="1.0.0.0" newVersion="2.0.0.0" />

 

<codeBase version="2.0.0.0" href="http://www.Wintellect.com/SomeClassLibrary.dll" />

 

</dependentAssembly>

 

<dependentAssembly>

 

<assemblyIdentity name="TypeLib" publicKeyToken="1f2e74e897abbcfe" culture="neutral"/>

 

<bindingRedirect

oldVersion="3.0.0.0­3.5.0.0" newVersion="4.0.0.0" />

 

<publisherPolicy apply="no" />

 

</dependentAssembly>

 

</assemblyBinding>

</runtime>

</configuration>

 

This XML file gives a wealth of information to the CLR. Here’s what it says:

 

probing elementLook in the application base directory’s AuxFiles and bin\subdir subdirec- tories when trying to find a weakly named assembly. For strongly named assemblies, the CLR looks in the GAC or in the URL specified by the codeBase element. The CLR looks in the appli- cation’s private paths for a strongly named assembly only if no codeBase element is specified.

First dependentAssembly, assemblyIdentity, and bindingRedirect elementsWhen at- tempting to locate version 1.0.0.0 of the culture-neutral SomeClassLibrary assembly published by the organization that controls the 32ab4ba45e0a69a1 public key token, locate version

2.0.0.0 of the same assembly instead.

 

codeBase elementWhen attempting to locate version 2.0.0.0 of the culture-neutral Some- ClassLibrary assembly published by the organization that controls the 32ab4ba45e0a69a1


public key token, try to find it at the following URL: www.Wintellect.com/SomeClassLibrary.dll. Although I didn’t mention it in Chapter 2, a codeBase element can also be used with weakly named assemblies. In this case, the assembly’s version number is ignored and should be omitted from the XML’s codeBase element. Also, the codeBase URL must refer to a directory under the application’s base directory.

Second dependentAssembly, assemblyIdentity, and bindingRedirect elementsWhen attempting to locate version 3.0.0.0 through version 3.5.0.0 inclusive of the culture-neutral TypeLib assembly published by the organization that controls the 1f2e74e897abbcfe public key token, locate version 4.0.0.0 of the same assembly instead.

publisherPolicy elementIf the organization that produces the TypeLib assembly has de-

ployed a publisher policy file (described in the next section), the CLR should ignore this file.

 

When compiling a method, the CLR determines the types and members being referenced. Using this information, the runtime determines, by looking in the referencing assembly’s AssemblyRef table, the assembly that was originally referenced when the calling assembly was built. The CLR then looks up the assembly/version in the application’s configuration file and applies any version number redi- rections; the CLR is now looking for this assembly/version.

If the publisherPolicy element's apply attribute is set to yes—or if the element is omitted— the CLR examines the GAC for the new assembly/version and applies any version number redirections that the publisher of the assembly feels is necessary; the CLR is now looking for this assembly/version. I’ll talk more about publisher policy in the next section. Finally, the CLR looks up the new assembly/ version in the machine’s Machine.config file and applies any version number redirections there.

At this point, the CLR knows the version of the assembly that it should load, and it attempts to load the assembly from the GAC. If the assembly isn’t in the GAC, and if there is no codeBase element,

the CLR probes for the assembly as I described in Chapter 2. If the configuration file that performs the last redirection also contains a codeBase element, the CLR attempts to load the assembly from the codeBase element’s specified URL.

Using these configuration files, an administrator can really control what assembly the CLR decides to load. If an application is experiencing a bug, the administrator can contact the publisher of the errant assembly. The publisher can send the administrator a new assembly that the administrator can install. By default, the CLR won’t load this new assembly because the already-built assemblies don’t reference the new version. However, the administrator can modify the application’s XML configuration file to instruct the CLR to load the new assembly.

If the administrator wants all applications on the machine to pick up the new assembly, the admin- istrator can modify the machine’s Machine.config file instead, and the CLR will load the new assembly whenever an application refers to the old assembly.

If the new assembly doesn’t fix the original bug, the administrator can delete the binding redirec- tion lines from the configuration file, and the application will behave as it did before. It’s important to note that the system allows the use of an assembly that doesn’t exactly match the assembly version recorded in the metadata. This extra flexibility is very handy.



Date: 2016-03-03; view: 698


<== previous page | next page ==>
Nbsp;   Privately Deploying Strongly Named Assemblies | Publisher Policy Control
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.01 sec.)