zoukankan      html  css  js  c++  java
  • 解决NopCommerce 在iis缓存目录Temporary ASP.NET Files下存在两个版本的dll问题(二)

    在上文解决NopCommerce 在iis缓存目录Temporary ASP.NET Files下存在两个版本的dll问题(一)中已经已经知道了在Nopcommerce中,只要插件项目里引用第三方dll时,把“复制本地”设置为False,插件就不会把第三方的dll复制到iis缓存目录,也就不会出现两个版本的dll问题。但是后来想想,在自己的插件引用的文件而站点没有引用的情况下,把插件引用的dll“复制本地”设置为False,那站点还是会有找不到引用文件的情况。于是就再去看看那个复nopcommerce项目专门处理插件输入目录的类PluginManager。

    在NopCommerce 3.9.0版的PluginManager类140行,有如下代码:

                     //load all other referenced assemblies now
                                foreach (var plugin in pluginFiles
                                    .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.InvariantCultureIgnoreCase))
                                    .Where(x => !IsAlreadyLoaded(x)))
                                        PerformFileDeploy(plugin);

    这段代码就是为了加载插件引用的第三方dll的。上篇文章提到了,官方文档是推荐插件引用的dll全部把“复制本地”设置为False

    Important: Going forward make sure "Copy local" properties of all third-party assembly references (including core libraries such as Nop.Services.dll or Nop.Web.Framework.dll) are set to "False" (do not copy)

    这里官方文档没有说全,实际上应该是如果站点已经引用到的情况下,插件引用的dll应该把“复制本地”设置为False,站点没有引用的,还是要照常输出到插件输出目录。

    再回过头来看类PluginManager加载插件引用dll的代码,既然已经有了这个方法,为何还会出现版本不一致的问题。看着这代码,最大的嫌疑就是IsAlreadyLoaded这个方法了,如果IsAlreadyLoaded为false,那么就会去插件输出目录寻找dll。

     看看IsAlreadyLoaded方法:

            private static bool IsAlreadyLoaded(FileInfo fileInfo)
            {
                //compare full assembly name
                //var fileAssemblyName = AssemblyName.GetAssemblyName(fileInfo.FullName);
                //foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
                //{
                //    if (a.FullName.Equals(fileAssemblyName.FullName, StringComparison.InvariantCultureIgnoreCase))
                //        return true;
                //}
                //return false;
    
                //do not compare the full assembly name, just filename
                try
                {
                    string fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileInfo.FullName);
                    if (fileNameWithoutExt == null)
                        throw new Exception(string.Format("Cannot get file extension for {0}", fileInfo.Name));
                    foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        string assemblyName = a.FullName.Split(new[] { ',' }).FirstOrDefault();
                        if (fileNameWithoutExt.Equals(assemblyName, StringComparison.InvariantCultureIgnoreCase))
                            return true;
                    }
                }
                catch (Exception exc)
                {
                    Debug.WriteLine("Cannot validate whether an assembly is already loaded. " + exc);
                }
                return false;
            }

     由此可见,PluginManager类判断dll是否已经加载是用

    AppDomain.CurrentDomain.GetAssemblies()

    调试发现,清空iis缓存目录第一次debug,进入插件初始化时,AppDomain.CurrentDomain.GetAssemblies()这方法加载89个程序集。

     第二次调试时,AppDomain.CurrentDomain.GetAssemblies()这个方法却只加载了22个程序集, 第二次调试时,虽然插件目录里出现的其他dll在iis缓存目录里存在,但这个方法都没获取到,所以会插件目录里的其他dll会被加载到iis缓存目录。

    但是为什么两次启动调试AppDomain.CurrentDomain.GetAssemblies()获取到的程序集会不一样呢?跟iis的机制有关?暂时不得而知。

    总结:nopcommerce进行插件开发的时候,引用的第三方文件如果是站点已经引用了的,需要把引用“复制本地”设置为False,如果站点没有引用,则还是要复制本地,否则如果不是全量更新而是抽包更新,会很容易出现插件目录dll与站点bin目录版本不同的情况,导致更新失败。

  • 相关阅读:
    ArcGIS案例学习笔记4_2
    ArcGIS案例学习笔记4_1
    ArcGIS案例学习笔记3_2
    ArcGIS案例学习笔记1_1
    ArcGIS案例学习1_2
    ArcGIS案例学习笔记2_1
    Window环境下配置Redis服务的方法及查看缓存数据的工具介绍
    C# 递归程序 获取某个节点下的全部子节点
    SQL查询中的in与join效率比较
    解决路由问题造成客户端无法访问服务器的方法之瞒天过海
  • 原文地址:https://www.cnblogs.com/basterdaidai/p/8098251.html
Copyright © 2011-2022 走看看