在加载XAML(或BAML)和接收根对象(例如Window)之间内部会发生什么?
首先出现在我脑海中的是Reflecton用于创建对象,设置其属性等等.但也许我错了?
也许有人可以解释如何在运行时解析和执行XAML/BAML,或者给出一篇包含解释的好文章的链接?
为了使我的问题更清楚一点,让我们讨论一下这个简短的例子:
<Button Margin="10">OK</Button>
Run Code Online (Sandbox Code Playgroud)
因此,解析器看到需要创建一个Button对象,其Margin属性必须设置为10并且其内容必须设置为"OK".怎么做的?通过使用Reflection(加上TypeConverters等)?
Mik*_*bel 27
您可能会在.xaml.cs文件中注意到支持已编译的XAML文件的partial类被标记为类.XAML构建任务生成第二个.cs文件,其中另一个部分类部分包含该IComponentConnector.InitializeComponent()方法的实现,该代码的实现由后面的代码中的默认构造函数调用.这个方法基本上贯穿XAML(此时实际上是BAML形式)并使用它来"修复"新创建的对象,而不是从XAML源创建一个新对象,如果你将会发生这种情况.是用来XamlReader加载或解析一个对象.
因此,当您实例化一个新编译的XAML对象(例如,a UserControl)时,InitializeComponent()在构造函数中调用之前的任何代码都将执行.然后,在调用期间将处理在XAML文件中设置的所有属性和事件处理程序InitializeComponent(),之后构造函数将继续执行.这可能很有用,因为您可能希望确保在处理XAML文件之前或之后设置某些属性.
至于如何解析XAML,它基本上被读作表示属性赋值,对象声明等的XAML节点流,这些节点由服务中的顺序执行System.Xaml.该节点流基于公共对象模型,该公共对象模型可以是从BAML流,XML文档(例如,松散.xaml文件),另一个对象实例等构建的.BAML 比基于XML的格式更紧凑,解析通常更快.
附录:在您添加的示例中,您询问解析器如何看到Button需要创建对象和Margin集合.简短的回答是:这取决于.具体来说,它取决于用于读取XAML流的模式上下文.
XAML解析器使用自己的类型系统,其中至少有两个实现:
System.ComponentModel;根据我对XAML语言规范的回忆,大致会发生什么:
StartObject该Button类型的节点(对于标准WPF命名空间映射)解析为该节点System.Windows.Controls.Button.这告诉解析器它需要创建一个Button对象的实例,它通过反射调用它的默认构造函数.StartMember节点,成员名称为Margin.WPF模式上下文的类型模型将此解析为Margin依赖项属性.Value接下来是一个节点,告诉解析器设置"10"(字符串)的值.解析器发现属性类型Thickness与字符串值不兼容.它查询其类型系统以查看[ValueSerializer]属性上是否存在Margin属性,该属性可用于转换字符串; 没有这样的属性.它检查属性的[TypeConverter]属性; 再一次,它找不到.它[TypeConverter]在Thickness类型本身上查找属性并找到一个属性,指示它使用a ThicknessConverter将字符串值转换为a Thickness.它就是这样.由于Margin是依赖属性,它使用SetValue()API来设置属性值; 如果它是CLR属性,它将使用反射或a PropertyDescriptor.EndMember节点告诉解析器结束属性赋值.Value包含内容的节点"OK".解析器知道它正在构造一个复杂的对象,因此内容不能代表整个对象.它查找[ContentProperty]属性Button及其超类型; 它找到一个on ContentControl,表示该值应该用于设置Content属性(它被解析为相应的依赖属性). Content是一个object,所以它string直接赋值(再次使用SetValue()).EndObject告诉解析器它已经完成了Button对象的处理.请注意,我使用术语"解析器"来简化操作.说实话,这一切都不会发生在解析阶段(如果"解析"阶段甚至存在).您可能认为"解析"阶段只是构建XAML节点流.声明对象的创建和/或填充实际上是通过将该流馈送到a XamlObjectWriter中来实现的,这简单地XamlWriter将XAML节点的实现写入对象(而不是XML文档或BAML流).在高层,只发生了两件事:
XamlReader 将某些内容转换为XAML节点流.XamlWriter 将XAML节点流转换为某种形式.在编译的XAML资源的情况下,编译时构建任务将a的输出管道XamlXmlReader化为BamlWriter"编译"XAML.在运行时,a的输入通过BamlReader管道输入XamlObjectWriter到创建或"修复"根对象.
一旦理解了所有这些,您就可以开始认识到XAML是一种强大的序列化和持久化格式,而不仅仅是构建UI的语言.
| 归档时间: |
|
| 查看次数: |
2058 次 |
| 最近记录: |