I looked through the ASP.NET MVC 2.0 source code and looked up how AreaRegistration.RegisterAllAreas();
is implemented. This line is usually put into the Global.asax Application_Start() method and internally it scans all Assemblies for types that implement the AreaRegistration abstract type. This is kinda the behaviour I’m after.
It appears RegisterAllAreas() makes a call to BuildManager.GetReferencedAssemblies()
, well if it’s good enough for MVC then it’s good enough for me 🙂
I’ve done some experimentation and BuildManager.GetReferencedAssemblies() will even pick up adhoc, random DLL’s dropped into the /bin folder, even with no references to any projects in the Visual Studio solution. So it appears far more reliable than AppDomain.Current.GetAssemblies()
.
I’ve rewritten my Assembly locator code to the following:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Compilation;
public static class AssemblyLocator
{
private static readonly ReadOnlyCollection<Assembly> AllAssemblies;
private static readonly ReadOnlyCollection<Assembly> BinAssemblies;
static AssemblyLocator()
{
AllAssemblies = new ReadOnlyCollection<Assembly>(
BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList());
IList<Assembly> binAssemblies = new List<Assembly>();
string binFolder = HttpRuntime.AppDomainAppPath + "bin\\";
IList<string> dllFiles = Directory.GetFiles(binFolder, "*.dll",
SearchOption.TopDirectoryOnly).ToList();
foreach (string dllFile in dllFiles)
{
AssemblyName assemblyName = AssemblyName.GetAssemblyName(dllFile);
Assembly locatedAssembly = AllAssemblies.FirstOrDefault(a =>
AssemblyName.ReferenceMatchesDefinition(
a.GetName(), assemblyName));
if (locatedAssembly != null)
{
binAssemblies.Add(locatedAssembly);
}
}
BinAssemblies = new ReadOnlyCollection<Assembly>(binAssemblies);
}
public static ReadOnlyCollection<Assembly> GetAssemblies()
{
return AllAssemblies;
}
public static ReadOnlyCollection<Assembly> GetBinFolderAssemblies()
{
return BinAssemblies;
}
}