c# – ASP.NET – AppDomain.CurrentDomain.GetAssemblies() – AppDomain重新启动后丢失的程序集

我有一个Bootstrapper,通过一个ASP.NET MVC应用程序中的所有程序集,查找实现一个IBootstrapperTask接口的类型,然后注册它们与IOC禁忌。这个想法是,你可以把你的IBootstrapperTasks放在任何地方,并组织你的项目如何你喜欢。

引导程序代码:

public class Bootstrapper
{
    static Bootstrapper()
    {
        Type bootStrapperType = typeof(IBootstrapperTask);

        IList<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();

        List<Type> tasks = new List<Type>();

        foreach (Assembly assembly in assemblies)
        {
            var types = from t in assembly.GetTypes()
                        where bootStrapperType.IsAssignableFrom(t)
                            && !t.IsInterface && !t.IsAbstract
                        select t;

            tasks.AddRange(types);
        }

        foreach (Type task in tasks)
        {
            if (!IocHelper.Container().Kernel.HasComponent(task.FullName))
            {
                IocHelper.Container().AddComponentLifeStyle(
                    task.FullName, task, LifestyleType.Transient);
            }
        }
    }

    public static void Run()
    {
        // Get all registered IBootstrapperTasks, call Execute() method
    }
}

完全构建后,AppDomain.CurrentDomain.GetAssemblies()返回我的解决方案中的所有程序集(包括所有的GAC,但不打扰我)。

但是,如果AppDomain重新启动,或者我弹出了Web.Config文件(添加空间并保存),则静态构造函数会再次运行,但是当调用AppDomain.CurrentDomain.GetAssemblies()时,大多数程序集都缺失,包括一个包含我的IBootstrapperTask类型。

我如何解决这个问题?我想我可以System.IO的/ bin目录,并手动加载所有的DLL,但宁愿避免这个如果可能,或者是唯一的方法?我是否采取正确的一般方法?

这是一个在.NET 4.0上运行的ASP.NET MVC 2.0应用程序,我在内置的Visual Studio 2010 Cassini Web服务器中遇到此问题,在Windows Server 2008上使用IIS7.0在集成管道模式下。

编辑:我刚刚遇到这个SO post Difference between AppDomain.GetAssemblies and BuildManager.GetReferencedAssemblies,说AppDomain只加载程序集,因为他们需要(例如,当一个方法/类从该程序集首先调用)。我想这将解释为什么装配缺少AppDomain.CurrentDomain.GetAssemblies()作为Bootstrapper运行非常早。

我注意到,如果我在启动程序之前从缺少的程序集中调用“某事”,例如:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        MyApp.MissingAssembly.SomeClass someClass =
            new MyApp.MissingAssembly.SomeClass();

        Bootstrapper.Run();
    }
}

…似乎解决了这个问题,但它是一个黑客。

我浏览了ASP.NET MVC 2.0源代码,并查找如何AreaRegistration.RegisterAllAreas();实现。这行通常放在Global.asax Application_Start()方法中,它在内部扫描所有实现AreaRegistration抽象类型类型的程序集。这是一种我以后的行为。

看来RegisterAllAreas()调用BuildManager.GetReferencedAssemblies(),好吧,如果它是足够好的MVC,那么它对我足够好:-)

我做了一些实验,BuildManager.GetReferencedAssemblies()甚至会拾取adhoc,随机DLL放入/ bin文件夹,即使没有任何项目在Visual Studio解决方案中的引用。所以它看起来远比AppDomain.Current.GetAssemblies()更可靠。

我已将我的Assembly Locator代码重写为以下内容:

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;
    }
}
http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c# – ASP.NET – AppDomain.CurrentDomain.GetAssemblies() – AppDomain重新启动后丢失的程序集