/// <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 }
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); }