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

C# 如何将不在磁盘上的程序集动态加载到ASP.Net Web应用程序中?,c#,asp.net,C#,Asp.net,我正在写一个原型来证明我正在研究的东西的可行性。基本上,它需要将不在磁盘上的程序集加载到应用程序域中。表面上看,这听起来很容易。事实上,这是WinForms世界中的儿童游戏,在WinForms世界中,进程就是进程 对于ASP.NETWeb应用程序来说,它有点松松垮垮。我已经让它工作了99.99%。当前方法的工作原理如下: public class AppDomainManager : System.AppDomainManager { PhantomAssemblyLoader m_ph

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

对于ASP.NETWeb应用程序来说,它有点松松垮垮。我已经让它工作了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。上面的代码加载所需的程序集,卸载它,再次加载它,依此类推。我知道发生这种情况是因为这些虚拟程序集中的静态数据在页面加载之间不存在

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

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

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

您可能希望在上查看MSDN文章,并研究在应用程序启动事件中加载程序集。

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

如果您阅读了,您将看到一个注释:

请勿使用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;
}

您的解决方案似乎位于winforms域中。这不是我的问题。我的问题特定于.Net Web应用程序。请提供Asp.Net的解决方案。在global.asax中创建引用并没有解决我的问题。我仍然不明白您试图实现什么。你能写一个例子来说明需求和WinForm解决方案吗?谢谢你的时间。一旦我的日程安排允许,我会试一试。