起因

经手一个asp.net 逐步转 asp.net core的项目,里面有一个经常变动的插件模块,每次插件增删的时候都要去改加载的地方,遂改成了根据命名规则自动加载,下面是很容易百度到的一句:

var plugins = AppDomain.CurrentDomain.GetAssemblies().Where(ab => ab.GetName().Name.StartsWith("Plugin.")).ToArray();

asp.net部分调试正常后发到iis上,没出现任何问题,然后过一会儿再访问发现部分插件没有加载;iis目录重新覆盖打包文件,调用正常,重启该web站点,问题重现。

分析

短暂的震惊之后,赶紧分析这肯定跟iis的回收有关,立即转为面向搜索引擎编程,查询关键字AppDomain GetAssemblies iis missing,很快找到原因;简单概括为:AppDomain为应用程序域,GetAssemblies()只会获取到已加载到当前域的程序集,iis应该是在站点目录文件更新之后第一次会加载所有的,回收或重启之后就只加载应用程序初始化必需的部分(后半部分是推断,不深究了,后面也会被替换掉)。 

解决办法

1.程序启动的时候把当前目录所有的dll都手动调用Assembly.Load()一遍就行了。

2.显然1不够优雅;这里asp.net与asp.net core就有差异了。asp.net用到了core首要干掉的 System.Web.dll(显然winform不会有这个问题);asp.net core使用了本身有包含的 Microsoft.Extensions.DependencyModel 。

asp.net:  var plugins = BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(ab => ab.GetName().Name.StartsWith("Plugin.*")).ToArray(); 

asp.net core:  var plugins = DependencyContext.Default.RuntimeLibraries.Where(o => o.Name.StartsWith("Plugin.")).Select(o => Assembly.Load(new AssemblyName(o.Name))).ToArray(); 

最後

相关参考:

https://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app

https://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl

https://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/

有些坑即使再浅,也得自己踩过才会知道。

posted on 2020-03-08 23:29  Cameron  阅读(3407)  评论(1编辑  收藏  举报