Inheritance: System.IO.FileNotFoundException
Beispiel #1
0
        /// <summary>
        /// this is fully reentrant and multithreading capable, but will itself block.
        /// </summary>
        private AssemblyDefinition Load(AssemblyNameReference name, string assemblyFilename, ReaderParameters parameters)
        {
            AssemblyDefinition ret = null;
            TaskCompletionSource<AssemblyDefinition> loadingTaskSource = new TaskCompletionSource<AssemblyDefinition>();

            bool nameRegistered = false, filenameRegistered = false;

            try
            {
                // First, make sure we are the only one loading.
                while (true)
                {
                    Task<AssemblyDefinition> loadingTask;
                    if (name != null && !nameRegistered)
                    {
                        if (loadingTasks.TryGetValue(name.Name, out loadingTask))
                        {
                            ret = loadingTask.Result;
                            return ret;
                        }

                        if (!loadingTasks.TryAdd(name.Name, loadingTaskSource.Task))
                            continue;
                        nameRegistered = true;
                    }

                    if (loadingTasks.TryAdd(assemblyFilename, loadingTaskSource.Task))
                    {
                        filenameRegistered = true;
                        break;
                    }
                    if (loadingTasks.TryGetValue(assemblyFilename, out loadingTask))
                    {
                        if (loadingTask == loadingTaskSource.Task)
                            break;

                        ret = loadingTask.Result;
                        return ret;
                    }
                }

                // now check if it has already been loaded.
                if (name != null)
                {
                    if (referencesByName.TryGetValue(name.Name, out ret))
                        return ret;
                }

                ret = fileNamesByAssembly.FirstOrDefault(v => v.Value.Equals(assemblyFilename, StringComparison.InvariantCultureIgnoreCase)).Key;
                if (ret != null)
                    return ret;

                // now load the assembly.
                Console.WriteLine("Loading {0}...", Path.GetFileName(assemblyFilename));

                AssemblyDefinition assm = AssemblyDefinition.ReadAssembly(assemblyFilename, parameters);

                VerifyFrameworkAssembly(assm, assemblyFilename);

                // have to use a lock to update both data structures at the same time.
                lock (referencesByName)
                {
                    // now check again by the assembly name if it has been loaded before.
                    // This can happen if we were only provided a file name
                    if (!referencesByName.TryAdd(assm.Name.Name, assm))
                    {
                        ret = referencesByName[assm.Name.Name];
                        return ret;
                    }

                    fileNamesByAssembly[assm] = assemblyFilename;
                }

                ret = assm;

                // now notify any listeners. note that if we were called on multiple threads
                // these might be called reentrantly as well.

                if(assemblyLoaded != null)
                    assemblyLoaded(ret);

                if (classLoader != null)
                    classLoader.LoadAssembly(ret);

                // done.
                return ret;
            }
            catch (Exception ex)
            {
            #if DEBUG
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            #endif
                // Log the error
                var assemblyName = name==null?assemblyFilename:name.ToString();
                DLog.Error(DContext.CompilerAssemblyResolver, "Failed to load assembly {0}: {1}", assemblyName, ex.Message);

                // Pass the error on
                var exn = new AssemblyResolutionException(name??new AssemblyNameDefinition(assemblyFilename, new Version()));
                loadingTaskSource.SetException(exn);
                throw exn;
            }
            finally
            {
                loadingTaskSource.TrySetResult(ret);

                // cleanup our registrations
                Task<AssemblyDefinition> ignore;
                if (nameRegistered)
                    loadingTasks.TryRemove(name.Name, out ignore);
                if (filenameRegistered)
                    loadingTasks.TryRemove(assemblyFilename, out ignore);
            }
        }