一遍又一遍地做同样的事情并期待不同的结果 - 精神错乱;也是我目前的心态
我有一种感觉,我只是错过了一些关键细节,或者我做了一些愚蠢的事情(参见 tl; dr )
我有一个ASP.NET Web API 2项目,我正在尝试支持“插件”程序集。插件程序集可以/将包含其他Web API控制器和其他类型的任意组合(数据提供程序,业务策略算法等)
MyProject.Common
(接口,合同等,由所有引用)MyProject.Core.Api
(仅引用Common
;加载Components
程序集)MyProject.Components.One
(也只引用Common
)MyProject.Components.Two
(也只引用Common
)我正在尝试将插件程序集隔离到plugins
目录。现在(测试)构建我正在将组件项目的输出( *.dll
)复制到MyProject.Core.Api\plugins
我正在尝试使用神奇的Application_Start()
方法加载插件程序集:
var directoryName = this.Server.MapPath("~/plugins");
var directoryInfo = new DirectoryInfo(directoryName);
var assemblySet = directoryInfo.GetFiles("*.dll")
.Select(fileInfo => Assembly.LoadFrom(fileInfo.FullName))
.ToList();
现在,我在致电HttpConfiguration.MapHttpAttributeRoutes()
之前完成所有这些操作,并考虑默认的IAssembliesResolver
服务为DefaultAssembliesResolver
,并考虑所有DefaultAssembliesResolver
所做的是:
return AppDomain.CurrentDomain.GetAssemblies().ToList();
在任何情况下,都无效,无法找到控制器。
从这里开始,我开始关注Customizing controller discovery in ASP.NET Web API并实施了自定义IAssembliesResolver
;相反,我根据博客文章从DefaultAssembliesResolver
派生。
这只是开始工作,当我还添加:
<configuration>
<runtime>
<assemblyBinding>
<probing privatePath="bin;plugins" />
但是,我看不到其他类型(数据提供商等)。我迭代了实现公共层接口的类型(我在其中一个组件项目中创建了MyTestThingy
)并尝试通过Activator.CreateInstance()
实例化它并得到{{1而§而不是
§:也许这与多次加载的程序集有关?
我认为我做错了什么,或者是在错误的时间。
我的目标最终是将null
文件夹中的所有该死的程序集加载到正在运行的~/plugins
中,以便可以解析Web API控制器,因此我可以使用组件实现其他事情。
我知道你不能“卸载程序集”,而是需要卸载AppDomain
,所以我希望,如果我需要刷新加载的程序集,我可以使用{{3强制重新加载/刷新下一个请求。
HttpRuntime.UnloadAppDomain()
,Assembly.LoadFile()
和Assembly.LoadFrom()
,而且他们使用不同的加载上下文(例如,我正在使用AppDomain
)LoadFrom()
共享IIS应用程序池的生命周期,我还应该考虑其他因素吗?我可以强制回收/重装吗?tl; dr - 在ASP.NET中没有简单的方法来管理运行时加载的“插件”程序集,特别是使用Web API,这样就可以提取
AppDomain
类型,什么/其他东西进入主机应用程序?而且,强制应用程序重新加载ApiController
,从而重新加载所有插件程序集?
Assembly.Load()
,坦白说它很蹩脚。我得到了它试图完成的任务,但它强加了一些愚蠢的约束(你必须克服API只是为了获得有目的地烘焙的导出类型列表,而不是实例)。AppDomain
与MAF