Clay 是 CodePlex 上的一个开源项目,扶助我们创立轻松成立对象,就
JavaScript 或其他动态语言同样简单。Clay 项目的网址是
http://clay.codeplex.com,Clay 近期主要利用于
Orchard
项目。以下2篇文章解释了Clay的背景:

Clay: malleable C# dynamic objects – part 1: why we need
it

Clay: malleable C# dynamic objects – part
2

以下内容来自上述2篇的简便摘录:

Orchard需求树立一种适于的数据结构用于在Orchard中承载视图模型(view
model)——由众多不等的实业毫无拘束地营造而成的时候,很快就变得卓殊显眼必需要用一种动态结构。

咱俩要求的是一分层协会:一个页面可能包罗一个博客作品列表和有些微件(widgets),而每篇博客小说是由众多构件组成的,比如评论,而评论又包括小编,小编又包罗头像、等级等等。

那就带出了第三个要求:多少个实体必须在互不知道对方的景况下一道创设那一个目的图(视图模型)。大家先行并不知道那些目的图的形状,且对象图的各种节点都很不难受到后来增添节点的震慑。

现行的难点是使用C#的静态类型来化解那几个要求是那一个不爽的。可以使用类似XML
DOM API 的 ChildNodes 和 Attributes 集合 以及 NodeName and Value
properties 的法子,而且那的确可以化解难题。可是绝半数以上人都会同意短期以来那种格局的API都是使开发人士呼天抢地的最主要原因,因而,除非用枪指着大家的头,否则大家都不想行使那种样式。

那种样式的API之所以极其令人咳嗽,最重大的原因是它首先让你取得到元数据,而把收获实际数目推到第二步API,比如Value。

现今应该相比较清楚C# 中的 XML
APIs之所以不爽,是因为静态语言不喜欢不可预感的东西,而想在编译时就清楚对象的百分之百细节。XML
APIs
接受预先精晓的(节点有所元数据是固定在结构里的),而把鲜为人知的东西推给属性。

换一种说法,元数据应该是目标的一个属性,而最后你收获的的确对象却是元数据结构的一个质量。

C# 4.0 提供了一个要命好的根本词适合各样各个的气象选取,它就是
dynamic

ExpandoObject
实际上是由此一种令人愕然方式达成的,那使得它尤其飞速。提醒:不是经过字典。又提醒:它是一个万分好的事物。

只是,根据API
可用性原则,它不够大胆,尤其是在创设深层次动态目的图方面它并从未给大家有些支持。它的表现也相比原则性且无法被增加。

一边,Clay 是莫大可增添的,且专注于深层次对象图的创建和拔取。

通过 Clay
你可以做的首先件工作就是创设一个简单的目的并在它上边安装属性。在此此前,大家将第一实例化一个给我们提供
语乌克兰语义糖衣的工厂。我盼望咱们可以跳过这一步而采取部分近似静态API的方法(译注:静态工厂方法),可是大家不可以。好了,正如你将见到的只需很小的代价:

dynamic New = ``new ClayFactory();

明天以此“New”对象将救助我们创制新的 Clay
对象,正如它的名字所暗示一样(即便这一个名字只是一个惯例而已)。

以下是局部大概且并未稍微新奇的事物:

var person = New.Person();

person.FirstName = ``"Louis"``;

person.LastName = ``"Dejardin"``;

那几个你都能由此 ExpandoObject
来形成的,不过此间比较有趣的地点是它有多样兑现格局,且开启了钻井潜能之窗。

诸如,在 Clay 中,索引语法与品质访问器是相等的,就好像 JavaScript
一样。当您在写代码通过名字去拜谒一个属性,而以此特性的名字在编译时刻又是不解的时候,那就足够实用了:

var person = New.Person();

person[``"FirstName"``] = ``"Louis"``;

person[``"LastName"``] = ``"Dejardin"``;

但还不止于此,你还足以将质量作为链式设置器来行使,像 jQuery这样:

var person = New.Person()

`.FirstName(“Louis”`)

`.LastName(“Dejardin”`);

或者,如若你喜爱,你还足以流传一个匿名对象:

var person = New.Person(``new {

`FirstName =“Louis”`,

`LastName =“Dejardin”`

});

更为好的是,Clay 还可以明了命名参数,大家得以那样写:

var person = New.Person(

`FirstName:“Louis”`,

`LastName:“Dejardin”`

);

总的说来,你可以使用很两种方法来设置属性和开头化 Clay 对象。

正如你所料,获取属性值也有种种形式且它们都是卓殊效果的:

person.FirstName

person[``"FirstName"``]

person.FirstName()

您也得以创设 JavaScript-style 数组:

var people = New.Array(

`New.Person().FirstName(“Louis”).LastName(“Dejardin”`),

`New.Person().FirstName(“Bertrand”).LastName(“Le Roy”`)

);

这种方法开创的数组也是一个完全的 Clay
对象,那象征你可以在运转时对它添加属性。

下一场,即使你想知道数组里的总项数,或者取得数组第一项的 FirstName
属性值,你可以那样:

people.Count

people[0].FirstName

当你想在一个早已存在的 Clay 对象上创制一个数组属性,那也卓殊简单:

person.Aliases(``"bleroy"``, ``"BoudinFatal"``);

比方有多于一个参数被传出,Clay
就会认为你正在开始化的这些特性是数组。不过只要惟有0或1个参数,你只虽显式地流传一个数组
(CLR or Clay):

person.Aliases(``new``[] {``"Lou"``});

比较 CLR 数组,Clay 数组能动态拉长:

person.Aliases.Add(``"loudej"``);

与此同时,它们也可以响应一些办法调用,如 AddRange, Insert, Remove, RemoveAt,
Contains, IndexOf, or CopyTo 。

综合起来,大家就可以透过一种越发简洁而又具有表现力的语法来创建一个非常复杂的靶子图:

var directory = New.Array(

``New.Person(

`FirstName:“Louis”`,

`LastName:“Dejardin”`,

`Aliases:new[] {“Lou”`}

``),

``New.Person(

`FirstName:“Bertrand”`,

`LastName:“Le Roy”`

`).Aliases(“bleroy”,“boudin”`),

``New.Person(

`FirstName:“Renaud”`,

`LastName:“Paquay”`

`).Aliases(“Your Scruminess”,“Chef”`)

).Name(``"Some Orchard folks"``);

最终一点自身想证明的是,Louis第一遍显示它给本人看的时候,我以为确实越发优雅和惊叹。

想像一下您有一个CLR接口须要贯彻,例如:

public interface IPerson {

`string` `FirstName {get;set`; }

`string` `LastName {get;set`; }

}

可是你想使用一个 Clay 对象,比如在上面定义的数组 persons
中一个要素。是的,你可以这么:

IPerson lou = people[0];

var fullName = lou.FirstName + ``" " + lou.LastName;

此地最特其他是 lou 是一个突出合法的静态类型 CLR
变量,你将获取任何智能感知和编译时检查。尽管大家没有写过完成这几个接口的具体品种,但它就是一个落到实处了
IPerson 的靶子。

可见落到实处如此玄而又玄的作用,是因为 Clay
重写了转移操作符,并为这些接口成立了一个动态代理(使用
Castle),这几个动态代理再托付成员调用给
Clay 对象。

故而,那是一个实在 CLR 类型,但它是在运转时被扭转的。

这就是使您可见写以下代码的:

foreach``(var person ``in directory) {

``Trace.Write(person.FirstName);

}

那边暴发了业务是: “directory” Clay 数组被转换成一个
IEnumerable,而有所相应的办法都因而 Clay 动态数组对象已毕。

连锁作品:

依赖 Clay 编写 不堪设想 的 c#
代码

http://weblogs.asp.net/bleroy/archive/tags/Clay/default.aspx

相关文章

网站地图xml地图