代码之家  ›  专栏  ›  技术社区  ›  Robert H.

如何将不在磁盘上的程序集动态加载到ASP.NET Web应用程序中?

  •  7
  • Robert H.  · 技术社区  · 16 年前

    我正在写一个原型来证明我正在研究的东西的可行性。基本上,它需要将不在磁盘上的程序集加载到应用程序域中。从表面上看,这听起来很简单。事实上,在一个过程是过程的Winforms世界里,这是孩子的游戏。

    对于ASP.NET Web应用程序,这有点奇怪。我让它工作99.99%。当前方法的工作原理如下:

    public class AppDomainManager : System.AppDomainManager
    {
        PhantomAssemblyLoader m_phantomAssemblyLoader;
        public AppDomainManager()
        {
            m_phantomAssemblyLoader = new PhantomAssemblyLoader();
        }
    
        public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
        {
            m_phantomAssemblyLoader.Attach(AppDomain.CurrentDomain);
        }
    }
    
    public class PhantomAssemblyLoader
    {
        public PhantomAssemblyLoader()
        {
        }
    
        public void Attach(AppDomain appDomain)
        {
            appDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolve);
            appDomain.DomainUnload += new EventHandler(DomainUnload);
        }
    
        public void Detach(AppDomain appDomain)
        {
            appDomain.AssemblyResolve -= AssemblyResolve;
            appDomain.DomainUnload -= DomainUnload;
        }
    
        void DomainUnload(object sender, EventArgs e)
        {
            this.Detach(sender as AppDomain);
        }
    
        private Assembly AssemblyResolve(object sender, ResolveEventArgs args)
        {
            Assembly asssembly = Assembly.Load(BlackMagic.GetBytes(sender, args));
            return asssembly;
        }
    }
    

    问题似乎是为每个页面加载实例化并卸载了一个新的AppDomain。上面的代码加载所需的程序集,卸载它,再次加载它,依此类推。我知道发生这种情况是因为这些幻影程序集中的静态数据在页面加载之间不持久。

    正确的解决方案可以将这些幻影程序集加载到与/bin文件夹中找到的程序集相同的上下文中。这些是在应用程序启动时加载的,在会话期间从不卸载。

    4 回复  |  直到 7 年前
        1
  •  11
  •   Pavel Chuchuva grapeot    16 年前

    如果你读 documentation on AppDomainManager 您将看到一条注释:

    不要使用AppDomainManager在ASP.NET中配置应用程序域。在ASP.NET中,配置必须由主机处理。

    因此,不应使用环境变量或注册表自定义AppDomainManager。

    我相信您只需将assemblyresolve事件处理程序添加到appdomain.currentdomain就可以实现您想要的。我创建了一个简单的网站,它按预期工作-动态程序集不会在页面加载之间卸载。

    protected void Page_Load(object sender, EventArgs e)
    {
       AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolve);
       Assembly assembly = Assembly.Load("PhantomAssembly");
       Type t = assembly.GetType("PhantomAssembly.Test");
       MethodInfo m = t.GetMethod("GetIt");
       Response.Write(m.Invoke(null, null));
       t.GetMethod("IncrementIt").Invoke(null, null);
    }
    
    private static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
    {
       Assembly asssembly = Assembly.Load(File.ReadAllBytes(@"C:\PhantomAssembly.dll"));
       return asssembly;
    }
    
        2
  •  1
  •   U62    16 年前

    如果问题是AppDomain在每个页面请求上都被创建和销毁,那么可以通过在ASP.NET应用程序状态下保存对它的引用来解决问题。例如,您可以在global.asax中创建一次。

        3
  •  1
  •   Mark    16 年前

    您可能想查看有关 ASP.NET Application Life Cycle 并调查在应用程序启动事件中加载程序集。

        4
  •  0
  •   Community CDub    8 年前

    My solution 对于类似的问题可能会有所帮助。