通用应用程序(Universal Application)的基石之一是.NET Native。这是微软的“云端编译器”,它能够把Windows应用商店中的程序编译成所支持的每种设备的机器代码。
.NET Native不使用JIT编译器,其结果是,用户可以在冷启动中节约最多达60%的时间,而在热启动中则最多达40%。编译器将查看整个应用程序,从而可以去掉用不到的功能,这在一些应用程序中可以节约最多达30%的空间。
第二块基石是叫做“自适应应用程序(adaptive app)”的概念。这个概念是指当应用程序所运行的设备上的一些功能和API并不存在时,仍然能够正常运行。只要遵循正确的模式,原生编译器就会去掉对那些在用户设备上不存在的API的引用。
.NET Native的另一个好处是,它允许微软以更快的节奏运转。应用程序静态链接到大部分框架库,这意味着你不太可能看到已发布应用程序的破坏性改动。开发人员必须明确选择可能破坏应用程序的新版本,这意味着微软不必过于担忧破坏性改动的问题。
最后,.NET Native使得微软在框架库中发现安全漏洞或者需要支持新的CPU架构时,可以自动重新编译应用程序。后者不仅仅停留在理论上,微软透露他们计划在今年秋天支持第四代CPU架构。
调试的工作流程
默认情况下,Windows 10应用程序在调试模式会编译成IL,而在发布模式会编译成原生代码。这可以通过项目属性窗口中的编译器标志来改变。开发人员大部分时间应该使用调试模式,因为.NET Native的构建时间明显要更长。
在设备上调试时,Visual Studio需要推送一个额外的库CoreCLR。这包括许多应用程序通常不需要的功能,所以当应用程序从Windows应用商店安装时不包括这个库。
版本号设置
在通用应用程序中,将不允许开发人员使用四位数字的版本号码。虽然开发人员还可以使用前三位数字,但是第四位数字保留由.NET Native编译器使用。
任何CPU
对通用应用程序,开发人员不能够指定任何CPU(Any CPU)为目标架构。微软要求应用程序的开发人员确实已针对目标硬件测试了他们的应用程序。
AppX打包选项
调试版本的程序包包含基于MSIL的库。调试模式的构建不适合设备上的旁加载(side-loading),因为设备上可能没有安装框架库的正确版本。
发布版本的程序包包含原生编译的库,带有发布所需的元数据。
运行时指令(rd.xml)
运行时指令(Runtime Directives)用于告诉编译器你要通过反射访问什么类型。如果你没有正确地列出类型,优化器可能会删除类型的元数据、甚至类型本身。
在运行时指令文件中指定过多信息的坏处是,你会无谓地增加应用程序的大小。如果这一点不成问题,那么你可以保留所有的默认设置。
.NET Native的最佳实践
在调试模式开发你的应用程序,可以获得更快的构建和测试周期。
定期在发布模式进行测试,以确保不会引入涉及.NET Native的错误。不要等到项目临结束时,才来解决原生的问题。
.NET Native的工作计划
对于将来的计划,微软打算减少原生编译应用程序的构建时间。他们也想要找到分享框架程序包的办法,从而减小应用程序在硬盘上的大小。
事后调试
如果你的应用程序在你无法访问的设备上崩溃,你就要从开发者门户获取调试符号(debug symbols)。使用这些符号需要匹配的源代码,因此请确保你有一个匹配的分支。
库
Windows 10通用应用程序与Windows 8.1将具有相同的外围应用(surface area)。“是的,WCF将可以在Windows Phone上运行。”未来版本的通用应用程序将通过NuGet随时发布。
便携式类库如果以.NET核心4.5.1为目标,则将照常工作。
行动呼吁
微软希望尽快知道在普通编译和.NET Native编译的行为之间是否有任何不同。请把问题报告到dotnetnative@microsoft.com。
欲知更多关于通用应用程序的信息,请观看Channel 9的视频, 深入了解XAML和.NET通用Windows应用程序的开发 。
查看英文原文: Deep Dive into Universal Applications
感谢邵思华对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群 )。