using System;
using System.Collections.Generic;
using System.IO;
namespace Core.Common.Assembly
{
///
/// Static class that tries to resolve any missing assemblies from the directory that
/// is provided during initialization. The contents of the assembly directory will be
/// iterated recursively up until the point where one or more assemblies are found.
///
/// When multiple assemblies are found with the same name, only the last one
/// will actually be resolved at runtime.
///
/// Given the following assembly directory structure:
///
/// -
///
/// Directory
/// -
///
/// Directory
/// -
/// Assembly_1.dll
///
///
b
///
/// -
///
/// Directory
/// -
/// Assembly_2.dll
///
/// -
/// Assembly_3.dll *
///
///
///
/// -
///
/// Directory
/// -
/// Assembly_4.dll
///
/// -
///
/// Directory
/// -
/// Assembly_5.dll
///
///
///
///
///
/// -
///
/// Directory
/// -
/// Assembly_3.dll **
///
/// -
/// Assembly_6.dll
///
///
///
///
///
///
/// Then the following assemblies will be resolved:
///
/// -
/// Assembly_1.dll
///
/// -
/// Assembly_2.dll
///
/// -
/// Assembly_3.dll **
///
/// -
/// Assembly_4.dll
///
/// -
/// Assembly_6.dll
///
///
///
public static class AssemblyResolver
{
private const string assemblySearchPattern = "*.dll";
private static Dictionary assemblyLookup = new Dictionary();
private static bool initialized;
///
/// Gets whether or not requires initialization.
///
public static bool RequiresInitialization => !initialized;
///
/// Initializes the .
///
/// The directory to recursively resolve any missing assemblies from.
/// Thrown when the
/// is already initialized.
/// Thrown when cannot
/// be found.
///
/// After successfully performing this method, equals false.
///
public static void Initialize(string assemblyDirectory)
{
if (initialized)
{
throw new InvalidOperationException("Cannot initialize the assembly resolver more than once.");
}
if (!Directory.Exists(assemblyDirectory))
{
throw new DirectoryNotFoundException($"Cannot find the directory '{assemblyDirectory}'.");
}
initialized = true;
InitializeAssemblyLookup(assemblyDirectory);
AppDomain.CurrentDomain.AssemblyResolve += LoadFileFromAssemblyLookup;
}
///
/// Resets the .
///
///
/// After performing this method, equals true.
///
public static void Reset()
{
initialized = false;
assemblyLookup = new Dictionary();
AppDomain.CurrentDomain.AssemblyResolve -= LoadFileFromAssemblyLookup;
}
private static void InitializeAssemblyLookup(string assemblyDirectory)
{
string[] assemblies = Directory.GetFiles(assemblyDirectory, assemblySearchPattern);
foreach (string directory in Directory.GetDirectories(assemblyDirectory))
{
InitializeAssemblyLookup(directory);
}
foreach (string assembly in assemblies)
{
assemblyLookup[Path.GetFileNameWithoutExtension(assembly)] = assembly;
}
}
private static System.Reflection.Assembly LoadFileFromAssemblyLookup(object sender, ResolveEventArgs args)
{
string assemblyName = args.Name.Substring(0, args.Name.IndexOf(','));
if (assemblyLookup.TryGetValue(assemblyName, out string assemblyFile))
{
return System.Reflection.Assembly.LoadFile(assemblyFile);
}
return null;
}
}
}