/// <inheritdoc /> public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) { if (assembly == null) { return(null); } if (EnableFrameworkRedirect && !FindExactMatch) { FrameworkRedirect.ApplyFrameworkRedirect(ref assembly, sourceModule); } #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var resolvedAssembly = Resolve2(assembly, sourceModule); if (resolvedAssembly == null) { var asmName = UTF8String.ToSystemStringOrEmpty(assembly.Name); var asmNameTrimmed = asmName.Trim(); if (asmName != asmNameTrimmed) { assembly = new AssemblyNameInfo { Name = asmNameTrimmed, Version = assembly.Version, PublicKeyOrToken = assembly.PublicKeyOrToken, Culture = assembly.Culture }; resolvedAssembly = Resolve2(assembly, sourceModule); } } if (resolvedAssembly == null) { // Make sure we don't search for this assembly again. This speeds up callers who // keep asking for this assembly when trying to resolve many different TypeRefs cachedAssemblies[GetAssemblyNameKey(assembly)] = null; return(null); } var key1 = GetAssemblyNameKey(resolvedAssembly); var key2 = GetAssemblyNameKey(assembly); AssemblyDef asm1, asm2; cachedAssemblies.TryGetValue(key1, out asm1); cachedAssemblies.TryGetValue(key2, out asm2); if (asm1 != resolvedAssembly && asm2 != resolvedAssembly) { if (EnableTypeDefCache) { foreach (var module in resolvedAssembly.Modules.GetSafeEnumerable()) { if (module != null) { module.EnableTypeDefFindCache = true; } } } } var inserted = false; if (!cachedAssemblies.ContainsKey(key1)) { cachedAssemblies.Add(key1, resolvedAssembly); inserted = true; } if (!cachedAssemblies.ContainsKey(key2)) { cachedAssemblies.Add(key2, resolvedAssembly); inserted = true; } if (inserted || asm1 == resolvedAssembly || asm2 == resolvedAssembly) { return(resolvedAssembly); } // Dupe assembly. Don't insert it. var dupeModule = resolvedAssembly.ManifestModule; if (dupeModule != null) { dupeModule.Dispose(); } return(asm1 ?? asm2); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif }
static AssemblyResolver() { gacInfos = new ThreadSafe.List <GacInfo>(); if (Type.GetType("Mono.Runtime") != null) { var dirs = new ThreadSafe.Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); extraMonoPaths = new ThreadSafe.List <string>(); foreach (var prefix in FindMonoPrefixes()) { var dir = Path.Combine(Path.Combine(Path.Combine(prefix, "lib"), "mono"), "gac"); if (dirs.ContainsKey(dir)) { continue; } dirs[dir] = true; if (Directory.Exists(dir)) { gacInfos.Add(new GacInfo(-1, "", Path.GetDirectoryName(dir), new[] { Path.GetFileName(dir) })); } dir = Path.GetDirectoryName(dir); foreach (var verDir in monoVerDirs) { var dir2 = Path.Combine(dir, verDir); if (Directory.Exists(dir2)) { extraMonoPaths.Add(dir2); } } } var paths = Environment.GetEnvironmentVariable("MONO_PATH"); if (paths != null) { foreach (var path in paths.Split(Path.PathSeparator)) { if (path != string.Empty && Directory.Exists(path)) { extraMonoPaths.Add(path); } } } } else { var windir = Environment.GetEnvironmentVariable("WINDIR"); if (!string.IsNullOrEmpty(windir)) { string path; // .NET 1.x and 2.x path = Path.Combine(windir, "assembly"); if (Directory.Exists(path)) { gacInfos.Add(new GacInfo(2, "", path, new[] { "GAC_32", "GAC_64", "GAC_MSIL", "GAC" })); } // .NET 4.x path = Path.Combine(Path.Combine(windir, "Microsoft.NET"), "assembly"); if (Directory.Exists(path)) { gacInfos.Add(new GacInfo(4, "v4.0_", path, new[] { "GAC_32", "GAC_64", "GAC_MSIL" })); } } } }
private void InitializeNestedClassesDictionary() { var table = tablesStream.NestedClassTable; var destTable = tablesStream.TypeDefTable; ThreadSafe.Dictionary <uint, bool> validTypeDefRids = null; var typeDefRidList = GetTypeDefRidList(); if (typeDefRidList.Length != destTable.Rows) { validTypeDefRids = new ThreadSafe.Dictionary <uint, bool>((int)typeDefRidList.Length); for (uint i = 0; i < typeDefRidList.Length; i++) { validTypeDefRids[typeDefRidList[i]] = true; } } var nestedRidsDict = new ThreadSafe.Dictionary <uint, bool>((int)table.Rows); var nestedRids = new ThreadSafe.List <uint>((int)table.Rows); // Need it so we add the rids in correct order for (uint rid = 1; rid <= table.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) { continue; } var row = tablesStream.ReadNestedClassRow(rid); if (row == null) { continue; // Should never happen since rid is valid } if (!destTable.IsValidRID(row.NestedClass) || !destTable.IsValidRID(row.EnclosingClass)) { continue; } if (nestedRidsDict.ContainsKey(row.NestedClass)) { continue; } nestedRidsDict[row.NestedClass] = true; nestedRids.Add(row.NestedClass); } var newTypeDefRidToNestedClasses = new ThreadSafe.Dictionary <uint, RandomRidList>(); foreach (var nestedRid in nestedRids) { var row = tablesStream.ReadNestedClassRow(GetNestedClassRid(nestedRid)); if (row == null) { continue; } RandomRidList ridList; if (!newTypeDefRidToNestedClasses.TryGetValue(row.EnclosingClass, out ridList)) { newTypeDefRidToNestedClasses[row.EnclosingClass] = ridList = new RandomRidList(); } ridList.Add(nestedRid); } var newNonNestedTypes = new RandomRidList((int)(destTable.Rows - nestedRidsDict.Count)); for (uint rid = 1; rid <= destTable.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) { continue; } if (nestedRidsDict.ContainsKey(rid)) { continue; } newNonNestedTypes.Add(rid); } Interlocked.CompareExchange(ref nonNestedTypes, newNonNestedTypes, null); // Initialize this one last since it's tested by the callers of this method Interlocked.CompareExchange(ref typeDefRidToNestedClasses, newTypeDefRidToNestedClasses, null); }