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 internal 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 (