跨平台开发——Banshee/Mono启示录

在接受Scott Hanselman的专访时,来自Novell的Aaron Bockover谈到了创建Banshee所遇到的挑战。Banshee是个跨平台应用,在Mono上采用C#构建,其目标平台是Linux、Max OS X及Windows。

Banshee由Aaron在2005年创建,其目标是为Linux平台创建一个媒体播放器。由于构建在Mono之上,因此它最终成为了一个跨平台应用,可以运行在Linux及Mac OS X(从1.4版开始)上,同时在今年的夏末秋初之际它将能够运行在Windows上。现在Banshee已经能构建并运行在Windows之上了,但在发布前还有一些修复工作要做。

创建Banshee的目的之一在于展示在Mono上构建应用的优势。该项目创建之时正赶上Mono的萌芽时期,那时没几个人相信它能成功。其他类似的应用还有F-Spot(一个照片管理应用)及Tomboy(一个记事本应用)。

Banshee因构建于Mono之上而受益无穷,不仅如此,Mono本身也在该媒体播放器的开发过程中对自身进行不断的改进,这也巩固了Mono,因此可以说这是一个双赢的结果。一个佐证就是在Mono的C#编译器增加了泛型功能后,Banshee是首个利用该特性的项目,同时在这个过程中一些bug也被揪出并得以修复。

Mono的编译器、垃圾收集器及JIT并非简单的将.NET代码移植到Linux上那么简单,而是根据规范重写了所有代码。其.NET程序库也是根据微软的文档基于公开API写成的。这么做的结果就是生成的MSIL字节码可以运行在任何平台上:Windows、Linux及Max OS。其与.NET平台的兼容性已经达到了无懈可击的地步了:.NET框架中的任何bug都会反映到Mono中以保证运行在不同平台上的应用都会执行同样的代码路径。这种跨平台的方式遇到了很多困难,首当其冲的就是文件访问。当在Mono中编写代码时,开发者并不会意识到应用将使用何种文件系统,POSIX还是FAT,抑或是NTFS。Mono对System.IO库有多种实现,为的就是在各种不同的文件系统上都能正常工作。

举个例子吧,看看System.IO.Directory.GetFiles()实现,该方法会返回一个数组。调用者需要等到方法构建好数组并返回后才能继续执行下面的代码,而一旦目录中含有大量文件时这么做的效率就很低下了。为了解决这个问题,开发者可以使用Mono.Posix程序库来探测目录中的文件,该方法会返回一个IEnumerable,这速度可快多了。

Banshee使用了一个IO抽象层(默认映射到System.IO)来实现跨平台的目的,然而一旦应用检测到了POSIX系统,它就会使用Mono.Posix程序库,因为其性能更好。

有两种抽象层:硬件抽象层及平台抽象层,前者的必要性显而易见,而后者的目的是充分利用平台所提供的最佳特性。比如说GNOME抽象层,它能禁用掉妨碍应用的屏幕保护程序,该抽象层构建在桌面环境所提供的特性之上。对于那些没有实现某些必备特性的平台来说,Mono通过扩展库的方式进行了实现,每个平台一个扩展库。.NET开发者可以使用这些继承了Mono.Addins的Mono程序库在Visual Studio中进行开发而无需在Mono上运行代码,因为这些库是插件,可以独立运行。

像Banshee这样的Mono应用可以在构建期检测其所运行的平台。构建程序会根据应用的目标运行平台创建核心组件和必要的插件。在Windows上,所有必要的信息都保存在解决方案文件中,该文件可以用Visual Studio打开,同时会在构建期加入所有必要的DLL。Linux的构建过程与Windows也没什么差异。Linux是在Linux机器上完成构建的,而Windows是在Windows PC上完成的。我们还可以在运行期检测平台,不过只在某些特定的情况下才这么做,并不推荐。

查看英文原文:Cross-platform Development – Lessons Learned from Banshee/Mono

你可能感兴趣的:(跨平台开发——Banshee/Mono启示录)