阿不

潜水

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

前言

话说Mono是一个非常有意思的平台,它提供了对.NET程序的跨平台迁移的可能性,它是一种看上去可以粉碎诟病者对.NET平台软件不具跨平台性质疑的技术。我非常喜欢.NET平台,同时我也非常希望它具备满足各种需要的特性,包括跨平台特性,因此我也对Mono技术非常感兴趣。由于我这两年以来一直在从事CMS开源项目的相关开发,在工作便利和技术研究的兴趣的驱动下,我一直非常希望能让Kooboo CMS支持Mono平台下的运行,进而也能进一步的让更多人了解Mono和Kooboo CMS。这是我近年来少有的一个明确的技术目标。

Kooboo CMS3.0版本,在去年完全重写了所有的代码,包括架构。在这次重写的过程中,增加了很多基于更小权限要求,更少依赖系统资源,更少的第三方程序集依赖等更具跨平台可能的考虑。

  • 更小的权限要求:以前我在写代码的时候,都不会考虑代码的运行安全问题,不管使用什么技术手段,能让程序正常运行起来就是唯一的目标。所以我经常会用一些需要具备比较高代码信任等级的代码。比如:emit;系统文件操作;无限制的反射代码;记录到系统事件日志等等很多需要Full trust level的代码运行权限。而这种的代码,会让程序在主机空间受到很大限制,甚至于运行不起来,从而造成这个项目无法被大量用户使用。另一方面,我认为,需要更高信任等级的代码,可能会在跨平台的迁移中带来更大的麻烦。因此,尽量把代码限制在尽可能小的拖管范畴之内会更有助于对Mono平台的支持,毕竟Mono也是没有完全实现.NET的所有功能。
  • 更少的依赖系统资源:这个就更加显而易见了。当我们使用了具有系统平台特征的功能和API时,要做迁移的时候就有可能因为某个功能和API的缺失而让我们不得不放弃。另一个例子,我们平常习惯了Windows平台下的开发,在做文件路径处理的时候我们很多人都会直接用”\”来拆分或合并,但是当你的代码中有大量这种潜规则的时候,就会给我们的迁移工作带来更大的麻烦。
  • 更少的依赖第三方程序集:这点不管是否需要具备迁移性,对于我们普通的开发也是非常重要的。当你依赖了很多第三方程序集的时候,当有其中一个不具备跨平台特性的话,那就非常麻烦了。

尽管在设计之初做了充分的考虑,也有一定的规划。但是最近一段时间以来的实践经验也告诉我,从.NET到Mono绝对不是一件很容易和轻松的事情,这之间你会遇到各种各样不可预知的问题。一方面,可能是因为Mono平台还不具备大规模的成功案例和充分测试使用,可能我们每个使用者在使用中都可能会发现其他人从来没有遇到过的问题和Bug;另一方面,不同系统平台的特点,让Mono不得不能出于兼容的考虑,或者其它方面的考虑,使用与普通的.NET环境不一样的配置环境,从而让我们的程序运行出错。尽管如此,我还是磕磕绊绊的走完了一半的路程,到目前为止,我已经可以成功的在Mono+Linux平台下让Kooboo CMS运行起来,并且可以做大部分的基础的事情。目前还有一些仍然绕不过去的问题等着我去研究解决,但可能还需要花费比较长的时间。

这个记录过程是以微博的形式简单记录,但是我认为,要让知识得到更好的总结和传播,博客的效应绝对会比微博来的方便和系统一些。所以我准备不定期的把我的迁移经验总结一下,希望这个总结的过程也能让我更具动力的去研究和解决在mono中遇到的各种问题(目前处于时断时续的状态)。今天先简单的总结一下Mono平台的.NET开发需要注意的一些基本注意事项。(另外,需要说明的是,这边只关注ASP.NET的Mono迁移,并不涉及Winform,Sivlerligh,WPF的Mono支持。)

基本注意事项

在Mono官网的这篇 Guidelines:Application Portability大体的介绍了下,从Windows平台的开发到Linux平台的迁移需要注意的一些要点。这些要点,我们上面都大致有过简单的介绍:

  • 大小写敏感问题。这是第一个,也是最经常出错的问题。虽然我不止一次的提醒自己在Liunx下面,任何字符串都是大小写敏感,包括文件路径,但我还是不止的在这个问题上在栽跟头。经常是一个样式或脚本怎么请求都无效,我还在那边检查是不是哪些的解析有问题了。但过了几十分钟之后发现,你的路径中某一个字符大小写不一致了。我认为,Linux的路径大小写问题真的很蛋疼,不管它有什么用处,Windows大小写不敏感不也用的好好的??
  • 路径分隔符,如上我所提到的在代码中直接使用“\”来拆分或合并路径。在这里,这种情况应该要被绝对杜绝。System.IO.Path这个类里面提供了很多API来帮我们处理到这些问题,请尽量养成用这个类的习惯吧。
  • 绝对路径问题,在linux下面,绝对路径的表达方式与Windows会有所不同。因此,还是尽量会一些系统的静态API来帮我们解决这些问题吧。
  • P/Invoke,这种操作也是绝对不允许的。因为你所调用的Win32 API,它所依赖的运行平台没有办法做到跨平台调用。
  • 注册表操作,同理,不应该出现这种情况 。
  • 底层的计算机指令的控制,这个我们写.NET程序应该几乎不会出现,略过。(IL代码不晓得是否可以跨平台?应该是不行吧。)

总之,它所有的要求就是遵从所有平台所共同具有的特性,尽量避免使用具备明显的特定平台特征的代码。除了,现有的Mono的官方文档所指出的明显不支持的那些功能之外,我们还会遇到各种它所没有提及的没有实现或来不及实现的一些技术细节,我遇到了一些问题包括:加密/解密类库的密钥长度与.NET不一样导致的,加密/解密失败(已经解决);不支持HealthMornitoring功能;对DataContractSerializer序列化反序化的格式不一致(目前仍然没有解决);对某些语言特性的编译不一致造成的编译失败。

关于Mono平台的兼容性,我们可以通过Compatibility文档了解一下,但是某些功能的兼容性在新版本已经有所变化。比如在2.10.2中,已经完全解决了MVC3的兼容问题。对于API的兼容性,我们可以通过这个链接:http://www.go-mono.com/status/ 来具备了解一下。

关于调试

如果我们直接把用VS编译好的程序拿到Mono/Linux下来运行的时候,出现任何问题,我们都无法简单的通过它的异常提示消息来得到很准备的问题原因。相同的一个功能,如果出现在Windows下运行正常,而Mono/linux下出错的话。除了调试,我们基本也没有更好的手段来排错。因此,我们做好使用在Mono/Linux下调试程序的准备。可能目前唯一的选择的是在Linux下,通过MonoDevelop运行程序来调试,这是目前最为简单的方法了吧。在这里,我们要知道,一个在VS编译好的程序,可以直接在Mono/Linux下运行,没有问题。但是这个程序的代码如果要用MonoDevelop,使用Mono运行时来编译的话,你可能就没有那么轻松过关了眨眼。不过,不用担心,只要我们把那些编译错误解决之后,使用MonoDevelop+XSP来调试的话,用户体验还是不错的。

本文结束大笑

posted on 2011-05-31 21:13  阿不  阅读(6185)  评论(18编辑  收藏  举报