ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - 组件的AppDomain重新启动后失踪 [英] ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - Assemblies missing after AppDomain restart

查看:105
本文介绍了ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - 组件的AppDomain重新启动后失踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个引导程序,看起来通过一个ASP.NET MVC应用程序的所有组件找到实施 IBootstrapperTask 接口类型,然后与国际奥委会Contrainer注册它们。这个想法是,你可以literaly将您IBootstrapperTasks的任何地方,并组织项目如何请你。

I have a Bootstrapper that looks through all Assemblies in an ASP.NET MVC application to find types that implement an IBootstrapperTask interface, and then registers them with an IOC Contrainer. The idea is that you can literaly place your IBootstrapperTasks anywhere, and organise your Projects how you please.

code为引导程序:

Code for Bootstrapper:

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一个人的,但这并不打扰我)。

After a full build, AppDomain.CurrentDomain.GetAssemblies() returns all Assemblies in my solution (including all the GAC one's but that doesn't bother me).

但是,如果在AppDomain重新启动,或者我'反弹'Web.Config文件(添加一个空格和保存),静态构造函数再次运行,但是当 AppDomain.CurrentDomain.GetAssemblies() 被称为大多数大会缺少,其中包含我的IBootstrapperTask类型之一。

However, if the AppDomain is restarted, or I 'bounce' the Web.Config file (adding a space and saving), the static constructor is run again but when AppDomain.CurrentDomain.GetAssemblies() is called, most of the Assemblies are missing, including the one containing my IBootstrapperTask types.

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

How do I get around this problem? I guess I could System.IO the /bin directory and load all the DLLs in there manually, but would rather avoid this if possible, or is that the only way? Am I taking the right general approach to this?

这是在.NET 4.0上运行的ASP.NET MVC 2.0应用程序,我得到这个问题与内置在Visual Studio 2010卡西尼Web服务器,并在IIS7.0集成管道模式的Windows Server 2008上。

This is an ASP.NET MVC 2.0 application running on .NET 4.0, I get this problem with the built-in Visual Studio 2010 Cassini web server, and with IIS7.0 in Integrated Pipeline Mode on Windows Server 2008.

编辑:我只是碰上了这种SO发布<一个href=\"http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembli\">http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembli它说在需要时才在AppDomain只加载大会(例如,当从组装方法/类首先调用)。我想这可以解释为什么大会缺少对 AppDomain.CurrentDomain.GetAssemblies()作为引导程序是很早就上运行。

I just came across this SO post http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembli which says the AppDomain only loads the Assemblies as they're needed (eg. when a method/class from that Assembly is first called). I guess that would explain why the Assemblies are missing on AppDomain.CurrentDomain.GetAssemblies() as the Bootstrapper is run very early on.

我注意到,如果我把一个电话'东西'从引导程序如之前丢失的大会:

I noticed if I placed a call to 'something' from the missing Assembly before the Bootstrapper eg:

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

        Bootstrapper.Run();
    }
}

...这似乎解决问题,但它是一个黑客攻击的一位。

...it seems to fix the problem, but it is a bit of a hack.

推荐答案

我在ASP.NET MVC 2.0源$ C ​​$ C看了又看了如何 AreaRegistration.RegisterAllAreas(); 实施。这条线通常被置于在Global.asax的Application_Start()方法,并在内部它扫描实现了AreaRegistration抽象类型类型的所有组件。这是有点儿我以后的行为。

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.

这似乎RegisterAllAreas()进行调用以 BuildManager.GetReferencedAssemblies(),如果是好足够好的MVC那么这对我来说不够好: - )

It appears RegisterAllAreas() makes a call to BuildManager.GetReferencedAssemblies(), well if it's good enough for MVC then it's good enough for me :-)

我已经做了一些试验和BuildManager.GetReferencedAssemblies()甚至会拿起即兴,随意DLL的投进/ bin文件夹,即使在Visual Studio解决方案的任何项目的引用。因此,它似乎比 AppDomain.Current.GetAssemblies更为可靠()

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().

我已经重写我的大会定位code以下内容:

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

这篇关于ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - 组件的AppDomain重新启动后失踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆