/// <inheritdoc/>
        public AssemblyDef Resolve(AssemblyNameInfo assembly, ModuleDef sourceModule)
        {
            if (assembly == null)
            {
                return(null);
            }

#if THREAD_SAFE
            theLock.EnterWriteLock(); try {
#endif
            AssemblyDef resolvedAssembly = Resolve2(assembly, sourceModule);
            if (resolvedAssembly == null)
            {
                string asmName        = UTF8String.ToSystemStringOrEmpty(assembly.Name);
                string asmNameTrimmed = asmName.Trim();
                if (asmName != asmNameTrimmed)
                {
                    assembly = new AssemblyNameInfo {
                        Name             = asmNameTrimmed,
                        Version          = assembly.Version,
                        PublicKeyOrToken = assembly.PublicKeyOrToken,
                        Locale           = assembly.Locale,
                    };
                    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(new AssemblyNameInfo(resolvedAssembly));
            var key2 = GetAssemblyNameKey(assembly);
            AssemblyDef asm1, asm2;
            cachedAssemblies.TryGetValue(key1, out asm1);
            cachedAssemblies.TryGetValue(key2, out asm2);

            if (asm1 != resolvedAssembly && asm2 != resolvedAssembly)
            {
                // This assembly was just resolved
                if (enableTypeDefCache)
                {
                    foreach (var module in resolvedAssembly.Modules.GetSafeEnumerable())
                    {
                        if (module != null)
                        {
                            module.EnableTypeDefFindCache = true;
                        }
                    }
                }
            }

            bool 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
        }