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

Rob*_* H. 7 c# asp.net

我正在写一个原型来证明我正在研究的东西的可行性.基本上,它需要将不在磁盘上的程序集加载到应用程序域中.从表面上看,听起来很容易.事实上,它是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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Pav*_*uva 11

如果您阅读有关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;
}
Run Code Online (Sandbox Code Playgroud)