.NET:CLR via C# Assembly Loading
7061 ワード
基礎知識
Internally, the CLR attempts to load this assembly by using the System.Reflection.Assembly class’s static Load method. This method is publicly documented, and you can call it to explicitly load an assembly into your AppDomain. This method is the CLR equivalent of Win32’s LoadLibrary function.
Internally, Load causes the CLR to apply a version-binding redirection policy to the assembly and looks for the assembly in the global assembly cache (GAC), followed by the application’s base directory, private path subdirectories, and codebase locations. If you call Load by passing a weakly named assembly, Load doesn’t apply a version-binding redirection policy to the assembly, and the CLR won’t look in the GAC for the assembly. If Load finds the specified assembly, it returns a reference to an Assembly object that represents the loaded assembly. If Load fails to find the specified assembly, it throws a System.IO.FileNotFoundException.
Some developers notice that System.AppDomain offers a Load method. Unlike Assembly’s static Load method, AppDomain’s Load method is an instance method that allows you to load an assembly into the specified AppDomain. This method was designed to be called by unmanaged code, and it allows a host to inject an assembly into a specific AppDomain. Managed code developers generally shouldn’t call this method because when AppDomain’s Load method is called, you pass it a string that identifies an assembly. The method then applies policy and searches the normal places looking for the assembly. Recall that an AppDomain has settings associated with it that tell the CLR how to look for assemblies. To load this assembly, the CLR will use the settings associated with the specified AppDomain, not the calling AppDomain.
However, AppDomain’s Load method returns a reference to an assembly. Because the System.Assembly class isn’t derived from System.MarshalByRefObject, the assembly object must be marshaled by value back to the calling AppDomain. But the CLR will now use the calling AppDomain’s settings to locate the assembly and load it. If the assembly can’t be found by using the calling AppDomain’s policy and search locations, a FileNotFoundException is thrown. This behavior is usually undesirable and is the reason that you should avoid AppDomain’s Load method.
Internally, LoadFrom first calls System.Reflection.AssemblyName’s static GetAssemblyName method, which opens the specified file, finds the AssemblyDef metadata table’s entry, and extracts the assembly identity information and returns it in a System.Reflection.AssemblyName object (the file is also closed). Then, LoadFrom internally calls Assembly’s Load method, passing it the AssemblyName object. At this point, the CLR applies a version-binding redirection policy and searches the various locations looking for a matching assembly. If Load finds the assembly, it will load it, and an Assembly object that represents the loaded assembly will be returned; LoadFrom returns this value. If Load fails to find an assembly, LoadFrom loads the assembly at the path name specified in LoadFrom’s argument. Of course, if an assembly with the same identity is already loaded, LoadFrom simply returns an Assembly object that represents the already loaded assembly.
Microsoft Visual Studio’s UI designers and other tools typically use Assembly’s LoadFile method. This method can load an assembly from any path and can be used to load an assembly with the same identity multiple times into a single AppDomain. This can happen as changes to an application’s UI are made in the designer/tool and the user rebuilds the assembly. When loading an assembly via LoadFile, the CLR will not resolve any dependencies automatically; your code must register with AppDomain’s AssemblyResolve event and have your event callback method explicitly load any dependent assemblies.
The ReflectionOnlyLoadFrom method will load the file specified by the path; the strongname identity of the file is not obtained, and the file is not searched for in the GAC or elsewhere. The ReflectionOnlyLoad method will search for the specified assembly looking in the GAC, application base directory, private paths, and codebases. However, unlike the Load method, the ReflectionOnlyLoad method does not apply versioning policies, so you will get the exact version that you specify. If you want to apply versioning policy yourself to an assembly identity, you can pass the string into AppDomain’s ApplyPolicy method.
インラインセット 1 private static Assembly ResolveEventHandler(Object sender, ResolveEventArgs args)
2 {
3 String dllName = new AssemblyName(args.Name).Name + ".dll";
4 var assem = Assembly.GetExecutingAssembly();
5 String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn =>
6 rn.EndsWith(dllName));
7 if (resourceName == null) return null; // Not found, maybe another handler will find it
8 using (var stream = assem.GetManifestResourceStream(resourceName))
9 {
10 Byte[] assemblyData = new Byte[stream.Length];
11 stream.Read(assemblyData, 0, assemblyData.Length);
12 return Assembly.Load(assemblyData);
13 }
14 }
1 private static Assembly ResolveEventHandler(Object sender, ResolveEventArgs args)
2 {
3 String dllName = new AssemblyName(args.Name).Name + ".dll";
4 var assem = Assembly.GetExecutingAssembly();
5 String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn =>
6 rn.EndsWith(dllName));
7 if (resourceName == null) return null; // Not found, maybe another handler will find it
8 using (var stream = assem.GetManifestResourceStream(resourceName))
9 {
10 Byte[] assemblyData = new Byte[stream.Length];
11 stream.Read(assemblyData, 0, assemblyData.Length);
12 return Assembly.Load(assemblyData);
13 }
14 }