/// <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
        }
Exemplo n.º 2
0
        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);
        }