You can use Assembly.GetReferencedAssemblies to get an AssemblyName[], and then call Assembly.Load(AssemblyName) on each of them. You'll need to recurse, of course - but preferably keeping track of assemblies you've already loaded :)
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
var loadedPaths = loadedAssemblies.Select(a => a.Location).ToArray();
var referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList();
toLoad.ForEach(path => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path))));
As Jon noted, the ideal solution would need to recurse into the dependencies for each of the loaded assemblies, but in my specific scenario I don't have to worry about it.
Update: The Managed Extensibility Framework (System.ComponentModel) included in .NET 4 has much better facilities for accomplishing things like this.
Yet another version (based on Daniel Schaffer answer) is the case when you might not need to load all Assemblies, but a predefined number of them:
var assembliesToLoad = { "MY_SLN.PROJECT_1", "MY_SLN.PROJECT_2" };
// First trying to get all in above list, however this might not
// load all of them, because CLR will exclude the ones
// which are not used in the code
List<Assembly> dataAssembliesNames =
AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => AssembliesToLoad.Any(a => assembly.GetName().Name == a))
.ToList();
var loadedPaths = dataAssembliesNames.Select(a => a.Location).ToArray();
var compareConfig = StringComparison.InvariantCultureIgnoreCase;
var referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Where(f =>
{
// filtering the ones which are in above list
var lastIndexOf = f.LastIndexOf("\\", compareConfig);
var dllIndex = f.LastIndexOf(".dll", compareConfig);
if (-1 == lastIndexOf || -1 == dllIndex)
{
return false;
}
return AssembliesToLoad.Any(aName => aName ==
f.Substring(lastIndexOf + 1, dllIndex - lastIndexOf - 1));
});
var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList();
toLoad.ForEach(path => dataAssembliesNames.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path))));
if (dataAssembliesNames.Count() != AssembliesToLoad.Length)
{
throw new Exception("Not all assemblies were loaded into the project!");
}
If you have assemblies where no code is referenced at compile time, those assemblies will not be included as a reference to your other assembly, even if you have added the project or nuget package as a reference. This is regardless of Debug or Release build settings, code optimization, etc. In these cases, you must explicitly call Assembly.LoadFrom(dllFileName) to get the assembly loaded.
In my winforms application I give JavaScript (in a WebView2 control) the possibility to call various .NET things, for example methods of Microsoft.VisualBasic.Interaction in the assembly Microsoft.VisualBasic.dll (such as InputBox() etc).
But my application as such does not use that assembly, so the assembly is never loaded.
So to force the assembly to load, I ended up simply adding this in my Form1_Load:
if (DateTime.Now < new DateTime(1000, 1, 1, 0, 0, 0)) { // never happens
Microsoft.VisualBasic.Interaction.Beep();
// you can add more things here
}
The compiler thinks that the assembly might be needed, but in reality this never happens of course.
Not a very sophisticated solution, but quick and dirty.