ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - Assemblies missing after AppDomain restart

寵の児 提交于 2019-11-27 12:04:17

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;
    }
}

Looks like you solved your own problem.

Edit: Personally, I would actually enumerate the assemblies, one by one, load them and look for the interface. Do it based of files rather than what the AppDomain is doing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!