我正在尝试使用 MEF 为 asp.net 网络表单制作某种插件系统。
到目前为止,我提供了一个解决方案,主机网站将在其插件文件夹中搜索以加载其他名为Module的网站。模块(插件)只是另一个网站项目,因此它的bin子文件夹中有自己的程序集。
您肯定已经知道,ASP.NET 应用程序不会在其bin文件夹之外加载 dll。因此,如果我尝试访问模块页面(例如:plugins/MyModule/Page.aspx)。我会收到一条错误消息,指出服务器无法加载程序集MyModule。我可以将模块的程序集放在主bin文件夹中,一切都会正常工作,但我想将所有模块文件保存在同一个文件夹中。
所以我正在寻找一种在bin文件夹之外加载程序集的方法。我试过弄乱 web.config 文件,但无法提供有效的解决方案。
然后我遇到了BuildManager类并编写了以下代码:
string pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");
foreach (string f in Directory.GetDirectories(pluginPath))
{
string binPath = Path.Combine(f, "bin");
if (Directory.Exists(binPath))
{
foreach (String file in Directory.GetFiles(binPath, "*.dll"))
{
Assembly a = Assembly.LoadFrom(file);
BuildManager.AddReferencedAssembly(a);
}
}
}
它在插件文件夹中搜索包含bin文件夹的任何其他子文件夹,并使用BuildManager加载相应的程序集。为了使这段代码工作,我必须在global.aspx程序集的PreApplicationStartMethod中调用它。
现在,当我导航到插件页面(plugin/MyModule/Page.aspx)时,它不会给我之前的错误,但页面是空白的。我检查了源代码,没有 html,什么都没有。我尝试调试页面,但从未调用Page_Load方法。所以我猜想Page.aspx背后的代码永远不会被调用。
编辑:
所以在搜索了更多之后,我在那里找到了一个解决方案:
当我加载一个模块程序集时,我将它的引用存储在一个字典中。然后在AppDomain.CurrentDomain.AssemblyResolve的事件处理程序中我返回相应的模块程序集。