/// <summary>
/// Given a qualified name of the form A.B.C.D, attempt to load
/// an assembly named after each of A.B.C.D, A.B.C, A.B, A. This
/// will only actually probe for the assembly once for each unique
/// namespace. Returns true if any assemblies were loaded.
/// </summary>
/// <remarks>
/// TODO item 3 "* Deprecate implicit loading of assemblies":
/// Set the fromFile flag if the name of the loaded assembly matches
/// the fully qualified name that was requested if the framework
/// actually loads an assembly.
/// Call ONLY for namespaces that HAVE NOT been cached yet.
/// </remarks>
public static bool LoadImplicit(string name, Action <Exception> assemblyLoadErrorHandler, bool warn = true)
{
string[] names = name.Split('.');
var loaded = false;
var s = "";
Assembly lastAssembly = null;
HashSet <Assembly> assembliesSet = null;
for (var i = 0; i < names.Length; i++)
{
s = i == 0 ? names[0] : s + "." + names[i];
if (!probed.ContainsKey(s))
{
if (assembliesSet == null)
{
assembliesSet = new HashSet <Assembly>(AppDomain.CurrentDomain.GetAssemblies());
}
Assembly a = FindLoadedAssembly(s);
try
{
if (a == null)
{
a = LoadAssemblyPath(s);
}
if (a == null)
{
a = LoadAssembly(s);
}
}
catch (FileLoadException e) { assemblyLoadErrorHandler(e); }
catch (BadImageFormatException e) { assemblyLoadErrorHandler(e); }
catch (System.Security.SecurityException e) { assemblyLoadErrorHandler(e); }
catch (PathTooLongException e) { assemblyLoadErrorHandler(e); }
if (a != null && !assembliesSet.Contains(a))
{
loaded = true;
lastAssembly = a;
}
probed[s] = 1;
}
}
// Deprecation warning
if (warn && loaded)
{
string location = Path.GetFileNameWithoutExtension(lastAssembly.Location);
string deprWarning = "The module was found, but not in a referenced namespace.\n" +
$"Implicit loading is deprecated. Please use clr.AddReference('{location}').";
Exceptions.deprecation(deprWarning);
}
return(loaded);
}