Clay:易塑的c#动态对象——第一部分:为什么我们需要它

当我正尝试建立一种合适的数据结构用于在Orchard中承载视图模型(view model)——由许多不同的实体毫无约束地构建而成的时候,很快就变得非常明显必须要用一种动态结构。

我们需要的是一分层结构:一个页面可能包涵一个博客文章列表和一些微件(widgets),而每篇博客文章是由许多部件组成的,比如评论,而评论又包涵作者,作者又包涵头像、等级等等。

这就带出了第二个需求:多个实体必须在互不知道对方的情况下共同构建那个对象图(视图模型)。我们预先并不知道这个对象图的形状,且对象图的每个节点都很容易受到后来扩展节点的影响。

现在的问题是使用C#的静态类型来解决这些需求是非常不爽的。

你可以使用类似XML DOM API 的  ChildNodes 和 Attributes 集合 以及 NodeName and Value properties 的方式,而且这确实能够解决问题。

但是我想,绝大多数人都会同意长期以来这种形式的API都是使开发人员痛不欲生的重要原因,因此,除非用枪指着我们的头,否则我们都不想使用这种形式。

这种形式的API之所以极其令人厌烦,最主要的原因是它首先让你获取到元数据,而把获取实际数据推到第二步API,比如Value。

在一个对象图中,你最关心的是节点的值(Value),其次是能够很容易就获得节点的子节点,通过索引或者名字(name)。

老实说,下面两种形式,你更喜欢哪种?

node.Attributes["rating"].Value

  

或者:

node.rating

  

Yeah,我认为是这样。第一种形式感觉好像是在用反射来获得非常简单属性的值。

好吧,现在应该比较清楚C# 中的 XML APIs之所以不爽,是因为静态语言不喜欢不可预知的东西,而想在编译时就知道对象的一切细节。XML APIs 接受预先知道的(节点拥有元数据是固化在结构里的),而把未知的东西推给属性。

换一种说法,元数据应该是对象的一个属性,而最终你得到的真正对象却是元数据结构的一个属性。

在总结之前,我想说一下对象初始化器(object initializers),它已经存在一段时间了,且经常被用来构造模糊可选项的参数,例如:

Html.TextBoxFor(m => m.CurrentUser, new {
  title = "Please type your user name",
  style = "float:right;"
})

 

必须清楚的是,虽然这些匿名对象在创建时非常灵活,但它们是常量,一旦被创建,你就不能再向它们添加新属性或方法,因此,它们不适合我们的用例。

幸运的是,C# 4.0 提供了一个非常好的关键词适合各种各样的情况使用,它就是dynamic

在part 2,我将展示 Clay (一个由Lou 编写的库)是如何漂亮而优雅地解决我们的问题的。

The Clay library: http://clay.codeplex.com

本贴第二部分:http://aprogrammer.net/2012/08/clay-malleable-c-dynamic-objects-part-2/

原文地址:http://aprogrammer.net/2012/08/clay-malleable-c-dynamic-objects-part-1-why-we-need-it/

posted on 2012-09-05 22:38  linven  阅读(294)  评论(0编辑  收藏  举报