silverlight使用:CLR 全面透彻解析: 使用 CoreCLR 编写 Silverlight

  CLR 全面透彻解析: 使用 CoreCLR 编写 Silverlight目录

  深入了解 CoreCLR 引擎

  CoreCLR 安全模型

  基类库

  跨平台运行

  Silverlight™ 2 包含对 Windows® Presentation Foundation (WPF) UI 框架所做大量更改:新Control控件、丰富网络 API 和数字版权管理 (DRM) 支持Silverlight 2 中项主要更改就是能够使用和 Microsoft® .NET 兼容语言编写 Web 客户端在本文中我将重点介绍 Silverlight 开发核心:CoreCLR

  在过去十几年中我们已经拥有了许多区别 Web 编程技术从 CSS 到 ECMAScript 变体其中大部分技术都特定于 Web 编程任务举例来说通过编程 CSS 所学到技术并不适用于其他领域相比的下Silverlight 2 允许您使用适用于桌面编程相同 .NET Framework 技术(如基类库、XAML 和 C#)还允许您将这些技术直接应用到 Web 客户端应用此外也无需创建单独 CoreCLR 开发环境:您可以直接使用 Visual Studio® 来设计、开发、调试和配置 C# 或 Visual Basic®就像使用桌面应用我们创建 Silverlight 2 CoreCLR 可使 Web 编程像桌面编程样丰富

  虽然拥有个丰富编程环境对开发人员很有好处但用户并不想下载大型浏览器插件为了使 Silverlight 适合用户使用必须实现快速安装我们已将 Beta 1 安装大小缩减到 4.3MB通过宽带连接大约需要 6 到 10 秒钟即可安装想想 .NET Framework 2.0 CLR 两个主要核心部件(mscorwks.dll 和 mscorlib.dll)大小大约都等于 Silverlight 2 coreclr.dll 和 mscorlib.dll 相加大小这真是很了不起成就

  深入了解 CoreCLR 引擎

  自 2005 年 10 月发行 CLR 2.0 版本后即开始了 CoreCLR 设计两个主要设计目标是大小和兼容性:从编程人员角度来看针对 CLR 编码应该始终相同而从用户角度来看下载必须非常小由于 Silverlight 旨在提供组区别于桌面 CLR 方案因此我们可以进行些更改以简化 CoreCLR 并允许我们缩减 Silverlight 安装大小但是堆栈底部致性至关重要行为差异(即使这些行为差异都正确)表明堆栈上部有

  为了确保兼容性我们在堆栈底部各个组件中使用相同代码执行引擎和虚拟机都是相同其中包括类型系统和元数据、垃圾回收器 (GC)、JIT 编译器、线程池以及运行时引擎其他核心部件

  但是为了适应 Web 应用方案进行了些更改例如富 Internet 应用通常简单且运行时间短JIT 编译器主要侧重于减少启动时间而非执行更复杂优化操作同样服务器垃圾回收模式可以对使用相似分配模式多个工作线程进行优化而对 Web 托管应用则行不通因此Silverlight 只包含针对交互式应用进行优化标准工作站 GC但是在 Silverlight 应用中使用 Microsoft 中间语言 (MSIL) 和元数据方式和在针对桌面托管应用使用方式完全相同而且应用行为在用户桌面上和在浏览器上

  事实上Silverlight 并不打算取代桌面 CLR这就引发了核心引擎中最大变化:CoreCLR 将和桌面 CLR 进程并行运行过去我们从来就不能在同进程中运行 CLR 两个版本这是个难题原因有好几个其中个是管理进程范围状态:每个 CLR 例子都假定进程中只有个 CLR因而只有它可以处理其静态数据如果 CLR 1.1 和 2.0 中都包含 Foo 变量而且在同个进程中同时加载了这两个 CLR 版本则任版本都无法在不影响另个 CLR 状态情况下写入 Foo 变量

  虽然进程范围状态是最明显问题但在个进程中并行运行两个 CLR 还会导致其他问题例如如果您同时运行了两个 GC如何防止其中个 GC 挂起另个 GC 线程?此外空间占用也存在问题:如果在个进程中加载多个 CLR每个 CLR 都必须加载代码(这些代码可能都相同)并为其静态变量和托管堆留出相应空间

  在某些重要情况下托管 CoreCLR 需要和桌面运行时并行运行如果 CoreCLR 和桌面 CLR 不能同时运行我们将无法编写托管 Web 浏览器Control控件(该Control控件可以导航到使用 Silverlight 网页)桌面 Windows 窗体或 WPF 应用若要解决这个潜在问题只需在您 Windows 计算机上安装依赖于 CLR Silverlight:每次安装 Windows XP SP2 和 Windows Vista® 时都会随操作系统安装相当新 CLR但是无论您计算机上安装了哪种版本 CLR(对于 Mac OS X 来说即使您计算机上未安装任何 CLR)只要使所有 Silverlight 代码在 CoreCLR 上运行都必须确保绝对兼容因此我们努力使 CoreCLR 可以和桌面 CLR 进程并行运行我们相信经过我们努力用户会获得更好 Silverlight 体验

  CoreCLR 安全模型

  核心引擎中个重大更改和新安全模型有关注意直以来.NET 开发人员使用代码访问安全性 (CAS) 来阻止不受信任代码执行特权操作CAS 功能非常强大但使用起来相当复杂它允许用户或管理员使用权限集定义各种代码沙箱然后将各个集映射到这些沙箱中对于 Silverlight 应用我们只需个沙箱该沙箱等效于 Internet Explorer® 用来在网页中运行脚本沙箱使用此简化方案我们可以删除所有 CAS 策略

  我们也简化了安全执行模型模型基于在 CLR 2.0 版本中引入个概念 — 安全透明透明模型本质是将代码分为以下 3类:透明代码、SafeCritical 代码或关键代码透明代码信任级别最低它无法提升权限或访问计算机上敏感资源或信息在 Silverlight 2 中所有应用代码都是透明代码关键代码信任级别最高它可以通过 P/Invoke 和系统进行交互甚至可以包含无法验证代码对于 Silverlight 2所有关键代码必须是 Silverlight 平台部分SafeCritical 代码则相当于 2者的间桥梁借助它透明代码可以通过关键代码来访问系统资源我们可以将关键代码想象成 Windows 内核 API;将透明代码想象成用户应用代码;而将 SafeCritical 代码想象成用户代码和内核代码的间 API

  透明代码只能其他透明代码或 SafeCritical 代码而 SafeCritical 代码可以代表用户代码关键代码SafeCritical 代码需要将输入规范标准化或调整为标准格式净化关键代码输出以保护系统安全性(参见图 1)

  CLR 全面透彻解析: 使用 CoreCLR 编写 Silverlight   图 1 CoreCLR 中安全执行机制

  将输入规范标准化为关键代码情况要比净化输出情况更简明易懂例如如果我 Web 应用需要在本地磁盘上写入个文件则使用独立存储即可实现此操作但是如果您不希望此应用写入名为“........bootmgr”文件中就必须确保输入格式正常、规范标准认为关键代码输出存在安全风险情况非常罕见主要安全概念是控制信息泄露在减小受到攻击者各种类型攻击方面起着至关重要作用假如我尝试访问系统上些用户信息获得响应是“权限被拒绝”但作为另个用户重复相同访问操作时我获得响应是“用户 Bob 不存在”如果我知道会获得这两种响应重复尝试无效访问就可以获得系统上用户名列表

  简化安全策略为使用 .NET 代码开发人员带来了极大便利同时也有助于开发人员研究 .NET 代码我们已尽可能少地使用关键代码和 SafeCritical 代码了如果使用大部分都是透明代码将有助于减少需要我们进行深入安全检查代码数量虽然仍要检查透明代码正确性和安全性但至少我们清楚这些代码不会执行任何特权操作许多 Silverlight 大型部件(包括动态语言运行时 (DLR))都是全部使用透明代码编写通过限制 Silverlight 特权部件我们可以将精力集中到确实需要仔细检查领域从而提高所交付产品安全性

  基类库

  .NET Framework 在桌面上演变发展是为了解决用户和服务器这两方面问题因此基类库 (BCL) 中很多功能在 Web 客户端上没有任何意义例如由于 Silverlight 不支持 CAS因此大部分 .Security 都不是必要诸如 .Console 等许多其他类在 Web 中也没有任何意义(既然如此为什么还要包含精简 .Console 类呢?它可以帮助我们测试产品)

  我们使用库和使用核心引擎目标是:将功能集减至最少以便 .NET 开发人员无需全面了解全新技术即可成功使用.NET Compact Framework 解决了区别情况中出现问题我们从中获得了些灵感和指导虽然我们从 Silverlight 中删除了 BCL但保留了 .NET Compact Framework 和 Silverlight 间兼容性通过此思路方法在所有平台的间共享个库可以在最大程度上重复使用 .NET 技术

  您可以在 BCL 中许多地方找到重复功能有些功能在 BCL 内部就是重复例如泛型集合和非泛型集合有时有些功能已经存在于基操作系统中如全球化支持我们不仅不必支持 Silverlight BCL 中所有替代选项还可以通过省略此重复行为来提供最佳性能和致性

  由于 .Net Framework 2.0 版本中引入了对泛型集合支持所以我们主张人们将注意力转移到泛型上在运行时 1.x 版本中通用数据结构必须基于对象相同核心数据结构类才能用来创建区别类型集合使用泛型类型参数编译器可以通过扩展这些通用数据结构来提供类型安全性从而使代码更易于编写和维护此外相对于非泛型集合来说泛型集合对值类型执行操作效果更好它不需要框起项目总的泛型不但可以提供非泛型集合提供所有功能而且由于不必使用重复所以 Silverlight BCL 中可以不包含诸如 ArrayList 等非泛型集合

  每个人或多或少都了解些全球化问题:许多欧洲地区将逗号用作小数点;中文数字将每 4位数分为组 (1000,0000)等等.NET Framework 在内部实施全球化功能因此它可以在多个领域正常运行为此它包含所有支持区域全球化数据使以 .NET 为目标应用在所有支持 Windows 版本中行为但是这也存在些弊端CLR 必须包含大型数据表而这些数据通常会随着时间流逝而失效此外这些数据都以 Windows 为中心因此某些 .NET 区域中数据和 Mac OS X 中相同区域区别鉴于这些原因CoreCLR 不包含自己全球化数据相反.Globalization.CultureInfo 可以使用宿主操作系统提供全球化功能因此Silverlight 应用在 Mac OS X 中运行时其行为更像 Mac而在 Windows 中运行时其行为更像 Windows 应用

  总的我们已经尽力在 CLR、.NET Compact Framework 和 Silverlight 的间维护类似 API 外围应用但在 BCL 中仍分散着其他细微差异例如由于 Silverlight 中有个单独 UI 线程因此它还包含个单独 Dispatcher 对象以承载 UI 工作项队列借助 Dispatcher您可以通过非 UI 线程更新 UI此代码允许您使用在其他线程(如后台线程)中创建集合更新 UI 元素 — MyListBox: MyListBox.Dispatcher.BeginInvoke( => MyListBox.ItemsSource = MyItems);

  我们建议在 Silverlight 中使用 .ComponentModel.BackgroundWorker它可以在完成时封装更新 UI但出于兼容性考虑我们仍将低级别线程 API 包括在内.Threading.ThreadPool.QueueUserWorkItem 和 .Threading.Monitor.Enter

  跟安全透明模型Silverlight BCL 中部分新增功能实际上在先前版本 .NET Framework 中就出现过独立存储就是其中个很好举例它可为经过沙箱处理应用提供虚拟化文件系统自 .NET Framework 1.0 推出以来独立存储就已存在但它仅适用于几种有限情况Silverlight 侧重于经过沙箱处理应用因此它可以完全利用独立存储: using (IsolatedStorageFile isoStore =
  IsolatedStorageFile.GetUserStoreForApplication)
{
  using (StreamWriter writer = StreamWriter(isoStore))
  {
     writer.Write("This is an isolated storage file.");
  }
}


  和 Web 浏览器中 Cookie 独立存储允许 Silverlight 应用维持其状态但是独立存储提供完全虚拟化文件系统支持目录和文件创建虽然独立存储不是为了存储高价值数据(如密码)但是其存储位置不明确而且仅限于拥有存储应用进行访问

  独立存储配额由应用组定义以 Silverlight 应用域名为基础例如如果两个 Microsoft 应用位于 microsoft.com 目录下则它们将共享个应用也就表示这两个应用共享相同配额默认情况下为每个应用组提供 1MB 存储区

  但是如果某个应用需要更多存储空间它可以通过个可指定对话框来提示用户以请求更大配额例如microsoft.com 需要将其配额增加到 8MB那么用户可以启用或禁用独立存储还可以在 Silverlight 配置对话框中删除当前使用独立存储(在对话框中称为应用存储)应用组还可以有共享存储区这就使相关应用可以共享其中数据

  虽然独立存储已经出现段时间但只有在 Silverlight 中使用后才引起人们关注适用于交互式 Web 应用可配置安全文件系统不仅可以开发文字处理等传统 Office 应用也可以开发维护大量数据应用如股票跟踪系统

  跨平台运行

  Silverlight 可以在非 Windows 平台上运行我们和 Novell 有合作在 Mono 项目 Moonlight 运行时整个过程中都支持 LinuxMicrosoft 还致力于研究适用于业界领先 Symbian OS 和 Windows Mobile® Silverlight 版本Moonlight 可以在 Mono 上运行而 Silverlight 移动版本可以在 .NET Compact Framework(其内存占用量比 CoreCLR 低)上运行但是Silverlight Mac OS X 版本只能在和 Windows 完全相同 CoreCLR 上运行

  我们只有在平台适配层 (PAL) 帮助下才能达到此目标此 PAL 是专为在区别平台上运行而编写 API它可为处理、文件处理、网络服务、线程语义等提供抽象层PAL 中功能可以共享 Win32® API 名称但实现过程却区别某些 API 只可以通过 PAL 功能参数传递到 OS X 功能中而其他 API 需要使用自定义逻辑才能使 OS X 功能和 Windows API 签名相匹配CoreCLR 使用若干 Windows 功能 Mac 中并不具备因此必须完全在 PAL 中实现(参见图 2)

  CLR 全面透彻解析: 使用 CoreCLR 编写 Silverlight   图 2 平台适配层

  许多 Silverlight PAL 得益于开发 Shared Source Common Language Infrastructure (SSCLI)(也称为 Rotor)所获得教训SSCLI 可以在许多 UNIX 类型平台和 Windows 上运行基操作系统功能因各个 UNIX 类型平台差异很大SSCLI PAL 必须同时在微内核(如 Mac OS X 中 Mach 内核)和单内核上才能运行并且需要处理线程、异常处理和网络堆栈等区别操作系统服务由于 Silverlight 仅适用于 Windows 和 Intel Mac 计算机因此我们能够为 PAL 中许多功能编写特定 Mac 实现这对 PAL 大小和性能很有帮助

  PAL 仅支持运行 Silverlight 必须使用 Win32 子集而无需支持注册表、GDI+ 或 COM我们不能在 OS X 的上实现 Windows也不能实现足够 Windows 功能来支持桌面 CLR 所有功能将 PAL 限制为仅支持 Silverlight 可以缩小其大小并加快执行速度

  当您意识到 OS X 和 Windows 的间差异有多大时就会了解隐藏操作系统的间差异是多么棘手问题大部分 OS X 使用 Objective C 编写而其提供异常处理系统和 C 不兼容CLR 创建 I/O 线程和工作线程区别这些 I/O 线程基于 Windows NT®3.5 中引入 I/O 完成端口而 OS X 中不存在此类端口由于 Windows 中存在反斜杠目录分隔符因此即使像查找文件这样简单操作在 Mac 上也不

  在 CoreCLR 整个设计和开发过程中我们侧重于使提供环境能让开发人员重用现有技术和工具以便为安全小型运行库开发更为丰富内容大部分决策驱动力都源自富 Internet 应用精减方案但部分设计还得益于过去工作成果对 CoreCLR 所做部分决策将最终在桌面上得到体现例如您可以期待桌面 CLR 个版本能够和 CLR 其他版本并行运行另外对改进安全透明模型所做大部分更改也会出现在下版本 CLR 中

  我们仔细考虑了哪些操作对基于 Web 方案有意义哪些在运行库中并无必要我们希望自己做出了正确选择而且相信您会对我们应如何继续改进提出建议来体会对 Silverlight 2 进行编写代码乐趣吧!请密切关注此内容以便将来继续深入探索 CoreCLR

  请将您想询问问题和提出意见发送至 [email protected]

  Andrew Pardoe 是 Microsoft CLR 团队(Team)名项目经理(project manager)他致力于从各个方面研究适用于 Silverlight 和桌面运行库两者执行引擎您可以通过电子邮件 [email protected] 和他联系

Tags:  silverlight.2.0 silverlight是什么 silverlight silverlight使用

延伸阅读

最新评论

发表评论