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

时间:2021-08-18 07:31:54

I'm writing a prototype to prove the feasibility of something I'm working on. Basically, it requires loading assemblies not on disk into an application domain. On the surface, it sounds easy. In fact, it's child's play in the WinForms world where a process is a process.

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

For the ASP.Net Web Applications, it's a bit squirrelly. I've got it working 99.99%. The current method is somewhat working like this:

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

The problem seems to be that a new AppDomain is instantiated and unloaded for each page load. The above code loads the required assembly, unloads it, loads it again and so on. I know this is happening because the static data within these phantom assemblies does not persist between page loads.

问题似乎是为每个页面加载实例化和卸载新的AppDomain。上面的代码加载了所需的程序集,卸载它,再次加载它等等。我知道这种情况正在发生,因为这些幻像程序集中的静态数据不会在页面加载之间持续存在。

The correct solution can load these phantom assemblies into the same context as those assemblies found in the /bin folder. These are loaded when the application starts and are never unloaded during the session.

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

4 个解决方案

#1


11  

If you read documentation on AppDomainManager you will see a note:

如果您阅读有关AppDomainManager的文档,您将看到一条注释:

Do not use AppDomainManager to configure an application domain in ASP.NET. In ASP.NET, configuration must be handled by the host.

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

Therefore, you should not use environment variables or registry to customize AppDomainManager.

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

I believe you can achieve what you want by simply adding AssemblyResolve event handler to AppDomain.CurrentDomain. I created simple website and it works as expected - dynamic assembly doesn't get unloaded between page loads.

我相信你可以通过简单地将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  

If the problem is that the AppDomain is getting created and destroyed on each page request, surely that can be solved by holding a reference to it in the ASP.NET Application state. You could create it once in the Global.asax for example.

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

#3


1  

You might want to check out the MSDN article on ASP.NET Application Life Cycle and investigate loading your Assembly in the Application_Start event.

您可能需要查看有关ASP.NET应用程序生命周期的MSDN文章,并调查在Application_Start事件中加载程序集。

#4


0  

My solution to a similar problem may be helpful.

我对类似问题的解决方案可能会有所帮助。

#1


11  

If you read documentation on AppDomainManager you will see a note:

如果您阅读有关AppDomainManager的文档,您将看到一条注释:

Do not use AppDomainManager to configure an application domain in ASP.NET. In ASP.NET, configuration must be handled by the host.

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

Therefore, you should not use environment variables or registry to customize AppDomainManager.

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

I believe you can achieve what you want by simply adding AssemblyResolve event handler to AppDomain.CurrentDomain. I created simple website and it works as expected - dynamic assembly doesn't get unloaded between page loads.

我相信你可以通过简单地将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  

If the problem is that the AppDomain is getting created and destroyed on each page request, surely that can be solved by holding a reference to it in the ASP.NET Application state. You could create it once in the Global.asax for example.

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

#3


1  

You might want to check out the MSDN article on ASP.NET Application Life Cycle and investigate loading your Assembly in the Application_Start event.

您可能需要查看有关ASP.NET应用程序生命周期的MSDN文章,并调查在Application_Start事件中加载程序集。

#4


0  

My solution to a similar problem may be helpful.

我对类似问题的解决方案可能会有所帮助。