第六周的NuGet软件包介绍 – Clay中动态、可塑、有趣的Expando对象与Clay

 

[原文发表地址]: NuGet Package of the Week #6 - Dynamic, Malleable, Enjoyable Expando Objects with Clay

[原文发表时间]:May 6, 2011, 4:41 AM

 

嘿,您实施了NuGet行动计划吗?行动起来吧,它只需5分钟——升级到1.2版本安装自动更新获取NuGet 软件包浏览器NuGet1.3已经out了,所以请确保您已经设置了自动更新!

 

故事背景:我正在思考既然NuGet.Net软件包管理网站开始逐渐充实,那么我应该开始在那寻找宝石了(没有双关含义)。您知道,就是那种大家可能没法发现的真正有用的东西。我将主要寻找开放源代码项目——我认为它们很有用。我会查看它们如何生成NuGet软件包,看看它们设计盒外(out of the box)安装体验时有没有什么有趣的地方(以及任何它们可以改进而实施的举措),当然也会关注软件包本身所做的事。

 

本周的推荐软件包是“Clay”。它使得用动态对象工作变得更有趣。它是Louis DeJardin和助手Bertrand LeRoy为开放源代码Orchard项目而编写的。

image

 

静态语言中有趣的动态

 

这是从我2年前的一篇关于C#动态关键字的文章中复制/粘贴来的一些内容。我认为内容不错,所以又把它添加到这里了。

 

所以我问这个人,动态关键字到底是什么,它到底是什么类型呢?我的意思是,C#不是动态的,对吗?他回答:

 

“哦,它是静态被赋予了动态类型。”

 

一瞬间我的大脑爆炸并溢出耳外。真的,尽管只有一秒钟的时间。这是Anders幻灯片里的一些很好的例子:

 

Calculator calc = GetCalculator();

int sum = calc.Add(10, 20);

 

这就是创建对象,方法调用以及返回值集合。下面是完全相同的代码,因为”var”类型在编译时被推算出来。

 

var calc = GetCalculator();

int sum = calc.Add(10, 20);

 

如果您想做同样的事,除了Reflection以外(比如如果它是其他类,可能是old-COM互操作,或者编译器不知道Add()的先验是否可行,等等)您可以这样做:

 

object calc = GetCalculator();

Type calcType = calc.GetType();

object res = calcType.InvokeMember("Add",

BindingFlags.InvokeMethod, null,

new object[] { 10, 20 });

int sum = Convert.ToInt32(res);

 

当然,它看起来很可怕。如果对象是动态的,我们可以这么做:

 

dynamic calc = GetCalculator();

int sum = calc.Add(10, 20);

 

然后获得动态方法调用和返回类型转换。基本上,看上去就像我们在调用其它任何对象一样。

 

我和我的好友``Rob Coner``y``都热爱动态语言,但我们也热爱.NET CLR。如果我们以自己的方式行事,就会给动态语言运行库和Iron.NET 语言更多支持。我们主要使用ASP.NET网页编写https://thisdeveloperslife.com 网站,因为这个网站主要使用动态的Razor模板引擎,而在代码中我们使用了动态类型。

 

有些人认为静态语言与动态语言没有任何关系,但我并不同意这一观点。正如他们所说的,成功编译只是第一次的单元测试,我喜欢能在静态与动态中做出选择。

 

Expando和动态

 

在.NET中,Expando对象是一个动态类型,您可以动态地为它添加或移除成员。它适合处理动态数据。您可以这样做:

 

dynamic myObject = new ExpandoObject();

myObject.WhateverMakesMeHappy = "Scott";

 

突然间,我有了一个新属性。您甚至可以将Expando“cast”成其他类型并按其他类型使用。这很疯狂。来操作吧。

 

通过对象初始化器生成匿名对象是个很好的选择,但一旦生成一个对象,它就会以那种方式固定不变。例如以下从Bertrand Le Roy的博客中截取的内容。

 

Html.TextBoxFor(m => m.CurrentUser, new {

title = "User Name",

style = "float:left;"

})

 

看到对象初始化器了吗?它生成了匿名对象,但是它将永远保持那种标题和样式。

 

为什么需要Clay?

 

引用Bertrand的话:

 

就API可用性而言, Expando对象并不创新,特别是它并不能帮助你生成深层动态对象图。其行为固定且不能扩展。

 

另一方面来说, Clay具有高度的可延伸性并侧重于深层图表的创建和使用。**

Clay有一个灵巧的命名规则(虽然你可能不喜欢它。放松,这只是个规则),在这种规则下您将ClayFactory实例命名为”New”。对的,首字母N大写-“New”。大脑又一次爆炸了。

 

当然,您可以通过Expando来实现的一般操作,也可以使用Clay来完成。但是,取决于具体情况的不同,您可以使用不同的技术,这也是有趣的地方所在。下面是 Bertrand 和 Lou提供的一些例子,以创建ClayFactory开头:

 

dynamic New = new ClayFactory();

 

现在这个“New”对象会帮助我们创建新的Clay对象,正如其名称所示(尽管这个名称只是一个规则)。然后:

 

var person = New.Person();

person.FirstName = "Louis";

person.LastName = "Dejardin";

 

比如在Clay中,索引器语法和属性访问器是等效的,就像它们在JavaScript中一样。

当你需要你通过名字访问某个属性,但是在编译时您又不知道名称的情况下,这是非常有用的

 

var person = New.Person();

person["FirstName"] = "Louis";

person["LastName"] = "Dejardin";

您还可以将属性当成可链接setter函数来用,风格同jQuery:

var person = New.Person()

.FirstName("Louis")

.LastName("Dejardin");

 

或者您可以传递一个匿名对象,此对象将成为一个Clay对象:

 

var person = New.Person(new {

FirstName = "Louis",

LastName = "Dejardin"

});

 

更好的是,Clay也理解命名参数,这样我们就可以写出如下内容:

 

var person = New.Person(

FirstName: "Louis",

LastName: "Dejardin"

);

 

或像这样的数组:

 

var people = New.Array(

New.Person().FirstName("Louis").LastName("Dejardin"),

New.Person().FirstName("Bertrand").LastName("Le Roy")

);

 

这些都意味着以下内容都是等效的:

 

var people = New.Array(

New.Person().FirstName("Louis").LastName("Dejardin"),

New.Person().FirstName("Bertrand").LastName("Le Roy")

);

 

要开始使用Clay,我推荐您安装Clay.Sample,而不用NuGet安装Clay软件包。这是开源项目的一个惯例,包含一个实例包,而这个实例包对项目本身有依赖关系。这样在安装完实例后,您就可以同时获得这两个包。

 

这里有一些其他不错的例子,它们能真正让您了解该如何像粘土(Clay)一样在动态和静态环境中切换:

 

public interface IPerson {

string FirstName { get; set; }

string LastName { get; set; }

}

public static void CastToCLRInterface() {

dynamic New = new ClayFactory();

var person = New.Person();

person.FirstName = "Louis";

person.LastName = "Dejardin";

// Concrete interface implementation gets magically created!

IPerson lou = person;

// You get intellisense and compile time check here

Console.WriteLine("{0} {1}", lou.FirstName, lou.LastName);

}

 

我想看到那些掌管大权的人,比如*咳*Anders*咳*签出像Clay的软件包这样的东西,并将它内置在语言里。这可就太好了。