2 // BaseAssemblyResolver.cs
5 // Jb Evain (jbevain@gmail.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace Mono.Cecil {
32 using System.Collections;
34 using SR = System.Reflection;
37 public abstract class BaseAssemblyResolver : IAssemblyResolver {
39 ArrayList m_directories;
40 string[] m_monoGacPaths;
42 public void AddSearchDirectory (string directory)
44 m_directories.Add (directory);
47 public void RemoveSearchDirectory (string directory)
49 m_directories.Remove (directory);
52 public string [] GetSearchDirectories ()
54 return (string []) m_directories.ToArray (typeof (string));
57 public virtual AssemblyDefinition Resolve (string fullName)
59 return Resolve (AssemblyNameReference.Parse (fullName));
62 public BaseAssemblyResolver ()
64 m_directories = new ArrayList ();
65 m_directories.Add (".");
66 m_directories.Add ("bin");
69 public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
71 AssemblyDefinition assembly;
72 string frameworkdir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName);
74 assembly = SearchDirectory (name, m_directories);
78 if (IsZero (name.Version)) {
79 assembly = SearchDirectory (name, new string [] {frameworkdir});
84 #if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
85 if (name.Name == "mscorlib") {
86 assembly = GetCorlib (name);
91 assembly = GetAssemblyInGac (name);
96 assembly = SearchDirectory (name, new string [] {frameworkdir});
100 throw new FileNotFoundException ("Could not resolve: " + name);
103 static readonly string [] _extentions = new string [] { ".dll", ".exe" };
105 static AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories)
107 foreach (string dir in directories) {
108 foreach (string ext in _extentions) {
109 string file = Path.Combine (dir, name.Name + ext);
110 if (File.Exists (file))
111 return AssemblyFactory.GetAssembly (file);
118 static bool IsZero (Version version)
120 return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
123 #if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
124 static AssemblyDefinition GetCorlib (AssemblyNameReference reference)
126 SR.AssemblyName corlib = typeof (object).Assembly.GetName ();
127 if (corlib.Version == reference.Version || IsZero (reference.Version))
128 return AssemblyFactory.GetAssembly (typeof (object).Module.FullyQualifiedName);
130 string path = Directory.GetParent (
131 Directory.GetParent (
132 typeof (object).Module.FullyQualifiedName).FullName
135 string runtime_path = null;
137 if (reference.Version.Major == 1)
138 runtime_path = "1.0";
139 else if (reference.Version.Major == 2) {
140 if (reference.Version.Minor == 1)
141 runtime_path = "2.1";
143 runtime_path = "2.0";
144 } else if (reference.Version.Major == 4)
145 runtime_path = "4.0";
147 switch (reference.Version.ToString ()) {
149 runtime_path = "v1.0.3705";
152 runtime_path = "v1.1.4322";
155 runtime_path = "v2.0.50727";
158 runtime_path = "v4.0.30319";
163 if (runtime_path == null)
164 throw new NotSupportedException ("Version not supported: " + reference.Version);
166 path = Path.Combine (path, runtime_path);
168 if (File.Exists (Path.Combine (path, "mscorlib.dll")))
169 return AssemblyFactory.GetAssembly (Path.Combine (path, "mscorlib.dll"));
174 public static bool OnMono ()
176 return typeof (object).Assembly.GetType ("System.MonoType", false) != null;
179 string[] MonoGacPaths {
181 if (m_monoGacPaths == null)
182 m_monoGacPaths = GetDefaultMonoGacPaths ();
183 return m_monoGacPaths;
187 static string[] GetDefaultMonoGacPaths ()
189 ArrayList paths = new ArrayList ();
190 string s = GetCurrentGacPath ();
193 string gacPathsEnv = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX");
194 if (gacPathsEnv != null && gacPathsEnv.Length > 0) {
195 string[] gacPrefixes = gacPathsEnv.Split (Path.PathSeparator);
196 foreach (string gacPrefix in gacPrefixes) {
197 if (gacPrefix != null && gacPrefix.Length > 0) {
198 string gac = Path.Combine (Path.Combine (Path.Combine (gacPrefix, "lib"), "mono"), "gac");
199 if (Directory.Exists (gac) && !paths.Contains (gac))
204 return (string[]) paths.ToArray (typeof (String));
207 AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
209 if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
213 foreach (string gacpath in MonoGacPaths) {
214 string s = GetAssemblyFile (reference, gacpath);
216 return AssemblyFactory.GetAssembly (s);
219 string currentGac = GetCurrentGacPath ();
220 if (currentGac == null)
223 string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"};
224 for (int i = 0; i < gacs.Length; i++) {
225 string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]);
226 string asm = GetAssemblyFile (reference, gac);
227 if (Directory.Exists (gac) && File.Exists (asm))
228 return AssemblyFactory.GetAssembly (asm);
235 static string GetAssemblyFile (AssemblyNameReference reference, string gac)
237 StringBuilder sb = new StringBuilder ();
238 sb.Append (reference.Version);
240 for (int i = 0; i < reference.PublicKeyToken.Length; i++)
241 sb.Append (reference.PublicKeyToken [i].ToString ("x2"));
243 return Path.Combine (
245 Path.Combine (gac, reference.Name), sb.ToString ()),
246 string.Concat (reference.Name, ".dll"));
249 static string GetCurrentGacPath ()
251 string file = typeof (Uri).Module.FullyQualifiedName;
252 if (!File.Exists (file))
255 return Directory.GetParent (
256 Directory.GetParent (
257 Path.GetDirectoryName (