背景:

不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有)

效果是这样的:

之后,有小部分用户反映,工具用不了(没反应或有异常)~~~

然后,建议小部分用户换个电脑环境试试,有些就好了~~~

于是,我假定是VS环境下的 Microsoft.VisualStudio.DebuggerVisualizers.dll 的版本不一致引发的。

因此,一般我都建议用户自己下载源码,重新引用去编绎一下!!!

由于该工具一直在CSDN论坛的VB.NET版块置顶着。

考虑到受众多,中间还偷偷升级过几回,解决了抛异常的问题,不过仍没有从根本性解决~~~~

这两天,有个叫子寒的同学,找上了我,希望我帮他解决这个问题。

我试着重新编绎了新版本发给他,都反馈木有效果。

只好让他下载源码,并在他电脑上进行远程调试。

昨晚处理到深夜1点半,终于:把发现的两个坑给埋了!!!

下面介绍下这两个坑:

1:as 转换的坑:

先看一段源码,这是拿到反序列化的结果,转Table,再绑定:

  1. protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
  2. {
  3. MDataTable dt = objectProvider.GetObject() as MDataTable;
  4. FormCreate.BindTable(windowService, dt, null);
  5. }

在这段代码中,调试的结果:

  1. objectProvider.GetObject() 拿到的对象是MDataTableGetType也返回的CYQ.Data.Table.MDataTable
  2.  
  3. as MDataTable 却返回了null

咦?一个大大的问号在我面前,同样的类型,怎么as不过去?

于是我把代码改了一下:

  1. MDataTable dt=(MDataTable)objectProvider.GetObject()

抛异常了:

  1. ************** 异常文本 **************
  2. System.InvalidCastException: [A]CYQ.Data.Table.MDataTable 无法强制转换为 [B]CYQ.Data.Table.MDataTable
    类型 A 源自“CYQ.Data, Version=5.7.5.5, Culture=neutral, PublicKeyToken=null”(在字节数组的上下文“LoadNeither”中)。
    类型 B 源自“CYQ.Data, Version=5.7.5.5, Culture=neutral, PublicKeyToken=null”(在上下文“LoadFrom”中的“C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Packages\Debugger\Visualizers\CYQ.Data.dll”位置处)。
  3. CYQ.Visualizer.MDataTableVisualizer.Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
  4. Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegatedHost.CreateViewer(IntPtr hwnd, HostServicesHelper hsh, SafeProxyWrapper proxy)

这个异常是什么等会再说,先补充知识点先:

  1. as 类型转换:只检测上下文中类型是否一致(或存在隐式转换),若失败返回null,不抛异常。
  2.  
  3. :强制类型转换:尝试进行类型转换,转换失败时,抛出异常。

好吧,第一个坑,相同的类型,没有异常,埋的够深!!!

AS叫了:这坑不能怪我,要怪就怪Assembly.LoadFrom,谁让你们把我们分隔在不同的上下文中。

2:Assembly.LoadFrom 的坑

这里再贴一段详细的异常信息:

  1. mscorlib
  2. 程序集版本:4.0.0.0
  3. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  4. 基本代码:file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
  5. ----------------------------------------
  6. Microsoft.VisualStudio.Platform.AppDomainManager
  7. 程序集版本:12.0.0.0
  8. Win32 版本:12.0.21005.1
  9. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/Microsoft.VisualStudio.Platform.AppDomainManager/v4.0_12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.Platform.AppDomainManager.dll
  10. ----------------------------------------
  11. System
  12. 程序集版本:4.0.0.0
  13. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  14. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
  15. ----------------------------------------
  16. System.Xml
  17. 程序集版本:4.0.0.0
  18. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  19. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll
  20. ----------------------------------------
  21. System.Configuration
  22. 程序集版本:4.0.0.0
  23. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  24. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
  25. ----------------------------------------
  26. System.Windows.Forms
  27. 程序集版本:4.0.0.0
  28. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  29. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
  30. ----------------------------------------
  31. System.Drawing
  32. 程序集版本:4.0.0.0
  33. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  34. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
  35. ----------------------------------------
  36. Microsoft.VisualStudio.DebuggerVisualizers
  37. 程序集版本:12.0.0.0
  38. Win32 版本:12.0.21005.1
  39. 基本代码:file:///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll
  40. ----------------------------------------
  41. CYQ.Visualizer
  42. 程序集版本:2.0.0.5
  43. Win32 版本:2.0.0.5
  44. 基本代码:file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%2012.0/Common7/Packages/Debugger/Visualizers/CYQ.Visualizer.dll
  45. ----------------------------------------
  46. CYQ.Data
  47. 程序集版本:5.7.5.5
  48. Win32 版本:5.7.5.5
  49. 基本代码:file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%2012.0/Common7/Packages/Debugger/Visualizers/CYQ.Data.DLL
  50. ----------------------------------------
  51. System.Data
  52. 程序集版本:4.0.0.0
  53. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  54. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_32/System.Data/v4.0_4.0.0.0__b77a5c561934e089/System.Data.dll
  55. ----------------------------------------
  56. System.Core
  57. 程序集版本:4.0.0.0
  58. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  59. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Core/v4.0_4.0.0.0__b77a5c561934e089/System.Core.dll
  60. ----------------------------------------
  61. CYQ.Data
  62. 程序集版本:5.7.5.5
  63. Win32 版本:12.0.21005.1
  64. 基本代码:file:///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll
  65. ----------------------------------------
  66. System.Numerics
  67. 程序集版本:4.0.0.0
  68. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  69. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Numerics/v4.0_4.0.0.0__b77a5c561934e089/System.Numerics.dll
  70. ----------------------------------------
  71. System.Transactions
  72. 程序集版本:4.0.0.0
  73. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  74. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_32/System.Transactions/v4.0_4.0.0.0__b77a5c561934e089/System.Transactions.dll
  75. ----------------------------------------
  76. System.EnterpriseServices
  77. 程序集版本:4.0.0.0
  78. Win32 版本:4.0.30319.36373 built by: FX452RTMLDR
  79. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_32/System.EnterpriseServices/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.EnterpriseServices.dll
  80. ----------------------------------------
  81. System.Windows.Forms.resources
  82. 程序集版本:4.0.0.0
  83. Win32 版本:4.0.30319.34209 built by: FX452RTMGDR
  84. 基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/System.Windows.Forms.resources.dll
  85. ----------------------------------------

************** 已加载的程序集 **************

异常里核心的两段:

  1. CYQ.Visualizer
  2. 程序集版本:2.0.0.5
  3. Win32 版本:2.0.0.5
  4. 基本代码:file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%2012.0/Common7/Packages/Debugger/Visualizers/CYQ.Visualizer.dll
  5. ----------------------------------------
  6. CYQ.Data
  7. 程序集版本:5.7.5.5
  8. Win32 版本:5.7.5.5
  9. 基本代码:file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%2012.0/Common7/Packages/Debugger/Visualizers/CYQ.Data.DLL
  10.  
  11. CYQ.Data
  12. 程序集版本:5.7.5.5
  13. Win32 版本:12.0.21005.1
  14. 基本代码:file:///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll

从上面的异常错误信息中,第一眼看是要蒙B的,毕竟少见多怪啊~~~~

大概花了8分钟,终于反应过来了,经过仔细的思考,可以发现:

  1. 1CYQ.Data CYQ.Visualizer.dll加载是在同一目录下。
  2.  
  3. 2:被Microsoft.VisualStudio.DebuggerVisualizers.dll加载却是在(上下文“LoadNeither”中,鬼知道这个LoadNeither是什么)。

于是,同一个dll被加载成两个不同路径,导致上下文环境不一样,而不能互转~~~~

为什么大部分正常,小部分环境会这么处理呢,目前无从知道,微软也是爱造坑的~~~

好吧,坑已经知道了,接下来如何埋才是重点:

1:埋坑思维一:测试下Assembly.Load、Assembly.LoadFile、Assembly.LoadFrom

写了几段测试代码:

  1. string filePath = AppDomain.CurrentDomain.BaseDirectory + "cyq\\CYQ.Data.dll";
  2. byte[] bytes = File.ReadAllBytes(filePath);
  3. Assembly ass = Assembly.Load(bytes);
  4. object o = ass.CreateInstance("CYQ.Data.Table.MDataTable");
  5. MDataTable dt = (MDataTable)o;

失败!

  1. string filePath = AppDomain.CurrentDomain.BaseDirectory + "cyq\\CYQ.Data.dll";
  2. Assembly ass = Assembly.LoadFrom(filePath);
  3. Assembly.LoadFile(filePath);
  4. ...省略...

都失败!!

测试这三个方法,主要是想看看有没有啥本质的不一样,特别是和强签名合在一起后~~~

把dll加个强签名试试~~~

仍失败~~~~

看来,我想多了,不同的dll路径加载的对象转换这条路是不通的了~~~~

2:埋坑思维二:强签名DLL,并注册到GAC中

理论上来说:该方式100%是可行的,毕竟路径的引用都是一致的。

方式也简单:通过代码加个注册的命令也不是什么难事~~~~

还是思考有没有其它更简洁的方式!

3:埋坑思维三:找个稳定的中介

既然问题出现在序列化前的MDataTable和反序列化后的MDataTable在不同上下文的dll而导致的。

那就就找一种第三方中介了:MDataTable=>中介(序列化)=》中介(反序列化)=>MDataTable

不用动脑,就可以想到两种:json或 DataTable。

于是代码就动起来了:

序列化时,用DataTable

反序列化时:

打完收工,重新编绎,发给用户测试,正常通过~

工具下载地址:

http://www.cnblogs.com/cyq1162/p/6027051.html

总结:

1:这么多年,第一次栽坑在as转换上,也许是没想到,也许是万万想不到。

2:不同的路径加载的相同的dll类型无法互转,这么多年终于遇上了,说明上的山多还是会见鬼的。

可既然版本号和签名都一致,又认为签名无法伪造,那为什么不呢?

为C# as 类型转换及Assembly.LoadFrom埋坑!的更多相关文章

  1. Assembly.LoadFrom加载程序集类型转换失败解决方法

    为了让我的wcf模块框架支持自定义通道上下文,对代码又进行了一次小型的重构,测试时发现类型转换的错误,最后发现是loadfrom引起的.如果向 loadfrom 上下文中加载了一个程序集,则将激活 l ...

  2. C#中的反射 Assembly.Load() Assembly.LoadFrom()

    一些关于C#反射的知识,估计也就最多达到使用API的程度,至于要深入了解,以现在的水平估计很难做到,所以下面此篇文章,以作为一个阶段的总结. 对于反射的总结,我想从以下几个方面展开,首先是反射程序集, ...

  3. Assembly.LoadFrom加载程序集无法释放资源的解决方案

    下面此方法加载程序集会导致程序集一直被占用 Assembly asm = Assembly.LoadFrom(dllPath); 解决方案: //通过此方法读取可以解决dll被占用问题 byte[] ...

  4. Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的区别!

    参考: http://www.cnblogs.com/benwu/archive/2009/10/24/1589096.html http://www.cnblogs.com/xuefeng1982/ ...

  5. 关于Assembly.LoadFrom和Assembly.LoadFile的区别

    区别: 1.Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("a.dll"),则载入a.dll,假如a.dll中引用了b.dll的 ...

  6. Assembly.LoadFrom() 方法加载程序集,无法转换类型

    有些情况在开发一个C#框架的时候,要用到反射加载另外程序集,这是必然考虑的事情.这样做的好处就是多个工程同时作业的时候,可以互不干扰,替换DLL文件即可. Assembly.Load();这个方法只能 ...

  7. cefglue埋坑记录

    很少写博客,写的不好,请多多包含,主要是记录工作中的一些问题,和园子里朋友一起讨论学习. 写埋坑记录之前,我先介绍下为什么会使用这个webkit内核的浏览器组件,我是wpf项目使用富文本编辑器,话说w ...

  8. 记 Maven 本地仓库埋坑之依赖包为何不能用

    记一次 Maven 本地仓库埋坑之 Verifying Availability 背景 某 Java 后端项目使用 maven 构建,因为某些原因,某些依赖库下载不了,直接找其它人索要了他电脑上的 m ...

  9. node-sass 埋坑记录

    node-sass 埋坑记录 背景 原有项目.环境: node:v8.16.2 npm:v6.4.1 node-sass::v4.8.0 Angular-CLI:v6.x 本机没有安装 Visual ...

随机推荐

  1. HTML URL地址解析

    通过JavaScript的location对象,可获取URL中的协议.主机名.端口.锚点.查询参数等信息. 示例 URL:http://www.akmsg.com/WebDemo/URLParsing ...

  2. iframe用法

    <iframe src="http://caiyanli.top/" height="500"  width="500" frameb ...

  3. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  4. OVS 中的各种网络设备 - 每天5分钟玩转 OpenStack(128)

    上一节我们启用了 Open vSwitch,本节将查看当前的网络状态并介绍 Open vSwitch 涉及的各种网络设备 初始网络状态 查看一下当前的网络状态. 控制节点 ifconfig 显示控制节 ...

  5. UWP开发之Mvvmlight实践八:为什么事件注销处理要写在OnNavigatingFrom中

    前一段开发UWP应用的时候因为系统返回按钮事件(SystemNavigationManager.GetForCurrentView().BackRequested)浪费了不少时间.现象就是在手机版的详 ...

  6. 用C语言封装OC对象(耐心阅读,非常重要)

    用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...

  7. PHP获取上个月最后一天的一个容易忽略的问题

    正常来说,PHP是有一个很方便的函数可以获取上个月时间的 strtotime (PHP 4, PHP 5, PHP 7) strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳 ...

  8. Atitit.软件研发团队建设原理与概论 理论

    Atitit.软件研发团队建设原理与概论 理论 培训 团队文化建设(内刊,ppt,书籍,杂志等) 梯队建设 技术储备人才的问题 团队建设--小红花评比. 团队建设--文化墙.doc 户外拓展 1. 团 ...

  9. Oozie分布式任务的工作流——Spark篇

    Spark是现在应用最广泛的分布式计算框架,oozie支持在它的调度中执行spark.在我的日常工作中,一部分工作就是基于oozie维护好每天的spark离线任务,合理的设计工作流并分配适合的参数对于 ...

  10. AutoMapper使用中的问题

    指定值只会执行一次 public class MomanBaseProfile : Profile { public MomanBaseProfile() { CreateMap<Request ...