#region License Information
/* HeuristicLab
* Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using HeuristicLab.Common;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
namespace HeuristicLab.CodeEditor {
internal class AssemblyLoader {
private readonly HashSet assemblySet = new HashSet();
private readonly object locker = new object();
public void AddAssembly(Assembly assembly) {
var assemblies = new[] { assembly };
OnAssembliesLoading(assemblies);
var unresolvedAssembly = Load(assembly);
lock (locker)
assemblySet.Add(unresolvedAssembly);
OnInternalAssembliesLoaded(new[] { unresolvedAssembly });
OnAssembliesLoaded(assemblies);
}
public void AddAssemblies(IEnumerable assemblies) {
var a = assemblies.ToArray();
OnAssembliesLoading(a);
var ua = new IUnresolvedAssembly[a.Length];
Parallel.For(0, a.Length, i => ua[i] = Load(a[i]));
lock (locker)
foreach (var asm in ua)
assemblySet.Add(asm);
OnInternalAssembliesLoaded(ua);
OnAssembliesLoaded(a);
}
public async Task AddAssembliesAsync(IEnumerable assemblies) {
await Task.Run(() => AddAssemblies(assemblies));
}
public void RemoveAssembly(Assembly assembly) {
var assemblies = new[] { assembly };
OnAssembliesUnloading(assemblies);
IUnresolvedAssembly unresolvedAssembly;
lock (locker) {
unresolvedAssembly = assemblySet.SingleOrDefault(x => x.FullAssemblyName == assembly.FullName);
assemblySet.Remove(unresolvedAssembly);
}
OnInternalAssembliesUnloaded(new[] { unresolvedAssembly });
OnAssembliesUnloaded(assemblies);
}
#region Loading Helper
private IUnresolvedAssembly Load(Assembly assembly) {
var loader = new CecilLoader {
DocumentationProvider = GetXmlDocumentation(assembly.Location)
};
return loader.LoadAssemblyFile(assembly.Location);
}
#endregion
#region XML Documentation Helpers
private static readonly List xmlDocLookupDirectories = new List {
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"),
System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
};
private static IDocumentationProvider GetXmlDocumentation(string assemblyLocation) {
if (!File.Exists(assemblyLocation)) return null;
string xmlDocFileName = Path.GetFileNameWithoutExtension(assemblyLocation) + ".xml";
foreach (var dir in xmlDocLookupDirectories) {
string xmlDocFileLocation = Path.Combine(dir, xmlDocFileName);
if (File.Exists(xmlDocFileLocation)) return new XmlDocumentationProvider(xmlDocFileLocation);
}
return null;
}
#endregion
#region Events
public event EventHandler>> AssembliesLoading;
private void OnAssembliesLoading(IEnumerable args) {
var handler = AssembliesLoading;
if (handler != null) handler(this, new EventArgs>(args));
}
public event EventHandler>> AssembliesLoaded;
private void OnAssembliesLoaded(IEnumerable args) {
var handler = AssembliesLoaded;
if (handler != null) handler(this, new EventArgs>(args));
}
public event EventHandler>> InternalAssembliesLoaded;
private void OnInternalAssembliesLoaded(IEnumerable args) {
var handler = InternalAssembliesLoaded;
if (handler != null) handler(this, new EventArgs>(args));
}
public event EventHandler>> AssembliesUnloading;
private void OnAssembliesUnloading(IEnumerable args) {
var handler = AssembliesUnloading;
if (handler != null) handler(this, new EventArgs>(args));
}
public event EventHandler>> AssembliesUnloaded;
private void OnAssembliesUnloaded(IEnumerable args) {
var handler = AssembliesUnloaded;
if (handler != null) handler(this, new EventArgs>(args));
}
public event EventHandler>> InternalAssembliesUnloaded;
private void OnInternalAssembliesUnloaded(IEnumerable args) {
var handler = InternalAssembliesUnloaded;
if (handler != null) handler(this, new EventArgs>(args));
}
#endregion
}
}