深入Silverlight(一)——Silverlight的架构

整体来看Silverlight由2部分构成:Core presentation framework(下面简称core部分)和 .NET Framework for Silverlight(下面简称.net部分),前者是用C++编写的SL的核心,后者则是用C#编写的编程框架。下图是安装了SL3之后,SL所在文件夹中的dll文件:

image

agcore是Core presentation framework的dll文件,除了微软SL的开发者之外,没有人可以通过正常的方法调用这个dll中的功能,其它dll文件则是以.net的习惯组织的.NET Framework for Silverlight的dll文件。你可以在MSDN中找到SL中的每个类属于哪个dll文件,也可以使用反射工具看到这些类的元信息。

下图来自MSDN,它是SL架构的官方版本:

SilverLight Architecture

这个图展示了core部分和.net部分分别承担了哪些功能,图中两个蓝色圆角矩形框分别表示core部分和.net部分。这张图大概传达的信息是准确的,不过详细去推敲的话,我觉得还是有些YY成分的。且这张图没有遵循任何标准格式,所以有些部分很让人费解。就我个人的观点,这张图有这么几个问题:

  1. XAML放到两部分中间非常奇怪,XAML parser是在core部分的,而二部分之间也不是通过XAML交互的
  2. core部分实际上跟.NET部分在UI上有一部分功能重叠,core部分负责的不想图中画的那样“底层”,布局工作大部分在core部分完成
  3. 类似UI core,BCL中的相当一部分也是在core中负责的

废话半天,下面进入正题,用reflactor看过SL的源码的同学一定会有印象,在SL的元素继承树中,一些非常上层的类都非常简单,如UIElement,Panel,Control等,这是因为他们的大部分功能实现在了core部分当中。对大部分开发者而言,关注.net部分的实现已经足够深入了,但是我想理解core部分和.NET部分的交互可以更有助于了解SL的整个原理。

SL的所有元素(注意,所有元素不是所有对象)采用了被称为peer logic的设计方式来避免垃圾回收和跨语言调用带来的问题,即每个.NET元素对象对应着一个Native对象,二者可以互相操作,互相调用,从意义上也表示同一个UI 元素,但是它们之间是互相引用关系。

在MS.Internal命名空间里 有两个非常重要的类:FrameworkCallbacks和XcpImports。FrameworkCallbacks是由core部分调用.NET部分的接口,XcpImports则是.NET部分调用core部分的接口,这两个类没有任何非静态方法或者字段,它们的作用基本上可以认为退化成了用于包含函数的命名空间。因为.NET和dll的不同特性,这两个类的结构也不尽相同。

XcpImports中的每一个callback对应着两个函数一个直接从dll中import进来的Native的函数,和一个简单封装把对象引用变成Int指针的函数,例如AddEventListener有如下两个版本:(代码来自元信息,不代表真实源码)

[DllImport("agcore", EntryPoint="AddEventListener", CharSet=CharSet.Unicode)]
private static extern uint AddEventListenerNative(IntPtr element, uint property, ref CValue outval, bool handledEventsToo);
 
internal static unsafe void AddEventListener(INativeCoreTypeWrapper obj, DependencyProperty property, string eventName, bool handledEventsToo)

 

AddEventListener仅仅负责将对象引用变成可以传入AddEventListener中的指针。

FrameworkCallbacks的情况略微复杂,以UpdateResource为例,在FrameworkCallbacks中包含一个delegate类型,一个delegate实例,以及一个函数

private static UpdateResourceDelegate _updateResourceDelegate;

[AllowReversePInvokeCalls, SecurityCritical] private static uint UpdateResource(IntPtr nativeDictionary, uint updateKind, [MarshalAs(UnmanagedType.LPWStr)] string key, IntPtr nativeInValue, out IntPtr nativeOutValue)

[SecurityCritical] internal delegate uint UpdateResourceDelegate(IntPtr nativeFrameworkElement, uint updateKind, [MarshalAs(UnmanagedType.LPWStr)] string key, IntPtr nativeInValue, out IntPtr nativeOutValue);

 

但是有趣的是,FrameworkCallbacks有一些特例,并非所有函数都定义在FrameworkCallbacks当中,一些控件的call back会被实现成它自己的静态方法(估计不少同学读源码的时候会被这类成员函数郁闷到:P),如

private static ItemsControl_ClearVisualChildrenDelegate _itemsControl_ClearVisualChildren;

你可以在ItemsControl中找到它对应静态方法的定义。

 

That’s all. 谢谢观赏。

posted @ 2009-10-04 00:17  winter-cn  阅读(...)  评论(... 编辑 收藏