#if NETFRAMEWORK // Taken from https://github.com/xunit/xunit/blob/master/src/common/AssemblyResolution/AssemblyHelper_Desktop.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Reflection; using Xunit.Abstractions; using Xunit.Sdk; namespace Xunit { /// /// This class provides assistance with assembly resolution for missing assemblies. /// class AssemblyHelper : LongLivedMarshalByRefObject, IDisposable { static readonly string[] Extensions = { ".dll", ".exe" }; readonly string directory; readonly IMessageSink internalDiagnosticsMessageSink; readonly Dictionary lookupCache = new Dictionary(); /// /// Constructs an instance using the given for resolution. /// /// The directory to use for resolving assemblies. public AssemblyHelper(string directory) : this(directory, null) { } /// /// Constructs an instance using the given for resolution. /// /// The directory to use for resolving assemblies. /// The message sink to send internal diagnostics messages to public AssemblyHelper(string directory, IMessageSink internalDiagnosticsMessageSink) { this.directory = directory; this.internalDiagnosticsMessageSink = internalDiagnosticsMessageSink; AppDomain.CurrentDomain.AssemblyResolve += Resolve; } /// public void Dispose() => AppDomain.CurrentDomain.AssemblyResolve -= Resolve; Assembly LoadAssembly(AssemblyName assemblyName) { if (lookupCache.TryGetValue(assemblyName.Name, out var result)) return result; var path = Path.Combine(directory, assemblyName.Name); result = ResolveAndLoadAssembly(path, out var resolvedAssemblyPath); if (internalDiagnosticsMessageSink != null) { if (result == null) internalDiagnosticsMessageSink.OnMessage(new DiagnosticMessage($"[AssemblyHelper_Desktop.LoadAssembly] Resolution for '{assemblyName.Name}' failed, passed down to next resolver")); else internalDiagnosticsMessageSink.OnMessage(new DiagnosticMessage($"[AssemblyHelper_Desktop.LoadAssembly] Resolved '{assemblyName.Name}' to '{resolvedAssemblyPath}'")); } lookupCache[assemblyName.Name] = result; return result; } Assembly Resolve(object sender, ResolveEventArgs args) => LoadAssembly(new AssemblyName(args.Name)); Assembly ResolveAndLoadAssembly(string pathWithoutExtension, out string resolvedAssemblyPath) { foreach (var extension in Extensions) { resolvedAssemblyPath = pathWithoutExtension + extension; try { if (File.Exists(resolvedAssemblyPath)) return Assembly.LoadFrom(resolvedAssemblyPath); } catch { } } resolvedAssemblyPath = null; return null; } /// /// Subscribes to the appropriate assembly resolution event, to provide automatic assembly resolution for /// an assembly and any of its dependencies. Depending on the target platform, this may include the use /// of the .deps.json file generated during the build process. /// /// An object which, when disposed, un-subscribes. public static IDisposable SubscribeResolveForAssembly(string assemblyFileName, IMessageSink internalDiagnosticsMessageSink = null) => new AssemblyHelper(Path.GetDirectoryName(Path.GetFullPath(assemblyFileName)), internalDiagnosticsMessageSink); /// /// Subscribes to the appropriate assembly resolution event, to provide automatic assembly resolution for /// an assembly and any of its dependencies. Depending on the target platform, this may include the use /// of the .deps.json file generated during the build process. /// /// An object which, when disposed, un-subscribes. public static IDisposable SubscribeResolveForAssembly(Type typeInAssembly, IMessageSink internalDiagnosticsMessageSink = null) => new AssemblyHelper(Path.GetDirectoryName(typeInAssembly.Assembly.Location), internalDiagnosticsMessageSink); } } #endif