每周源代码12 – 暗夜回归版本

[原文发表地址] The Weekly Source Code 12 - Back in Black Edition

[原文发表时间] 2008-01-08 11:43

距离上次的每周源代码有段时间了,不过我有假期和照顾小娃娃作为很好的正当理由。现在我从父亲的身份中回来了,所以我的每周源代码也将和我承诺的那样恢复每周一篇了。

如果你是新来的,我要告诉你每周我都会在这里贴上些我觉得很有趣的(解读:美丽的,丑陋的,聪明的,缺德的)源代码片段以及出自的项目。我之所以做这件事是本着我一贯的信念,那就是阅读源代码和写代码一样重要,甚至更为重要。我们阅读各种计算机书籍来成为更好的程序员,但除非你是阅读像《编程珠玑》这样的书籍,不然你必须不断研读各种开放源项目来寻找灵感。

所以,亲爱的读者,在这里为你们奉上第12篇每周源代码,之后还会有无数篇。这是我换婴儿尿布时读的源代码。

想要寻找使用WPF的应用吗?它们就在那儿,没有“垂涎欲滴的按钮”,也不会大声嚷嚷“我是用WPF写的”。一般它们只是很清晰,简单而且功效十足。Witty是一个用WPF 写的Twitter客户端,是一项我尚未完全参透的技术。

这个小应用内含一个简单的Twitter客户端库,包括了一个TinyUrl生成器。(Google最好买下TinyUrl,否则整个网络可能变成一坨混乱的链接)有时读源代码的注释很欢乐,而读一些不是你写的代码时,如果你对自己说“嗯这里可以用一些重构”,那种感觉也很舒畅。也许这就是你为开放源项目做贡献的好时候了。

这个例子不过是Witty代码中最平凡不过的了,但我看了总禁不住微笑。Witty的主窗口也有些很有趣的东西,尤其是后台获取数据,绝对比Winforms的简单很多。

public void UpdateRelativeTime()

{

DateTime StatusCreatedDate = (DateTime)dateCreated;

TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - StatusCreatedDate.Ticks);

double delta = ts.TotalSeconds;

string relativeTime = string.Empty;

if (delta == 1)

{

relativeTime = "a second ago";

}

else if (delta < 60)

{

relativeTime = ts.Seconds + " seconds ago";

}

else if (delta < 120)

{

relativeTime = "about a minute ago";

}

else if (delta < (45 * 60))

{

relativeTime = ts.Minutes + " minutes ago";

}

else if (delta < (90 * 60))

{

relativeTime = "about an hour ago";

}

else if (delta < (24 * 60 * 60))

{

relativeTime = "about " + ts.Hours + " hours ago";

}

else if (delta < (48 * 60 * 60))

{

relativeTime = "1 day ago";

}

else

{

relativeTime = ts.Days + " days ago";

}

RelativeTime = relativeTime;

}

同行们都在关注C# 3.0,希望让lambdas表达式和匿名类型声明从感觉和行为上都能接近Ruby的哈希表声明。很想知道Anders是否已经开始着手做这个了。我在想他和Matz平时在不在一块儿玩儿。如果我要发明一种语言,我会为他俩建造一个专属俱乐部。; )

Eilon在他的提议中展示了Dictionaries和匿名类型的区别:

o 这是些不怎么好看的代码:

Dictionary<string, string> values = new Dictionary<string, string>();

values.Add("key1", "value1");

values.Add("key2", "value2");

values.Add("key3", "value3");

GetHtmlLink("Click me", values);

我的提议:让函数接受类型对象的参数。调用者可以传入一个有合适名字和值的属性的类型。他们可以通过C#对象初始句法来节省空间:

MyParams myParams = new MyParams { Key1 = "value1", Key2 = "value2", Key3 = "value3" };

GetHtmlLink("Click me", myParams);

不过,这还有个额外的工作,那就是要定义MyParams类型。要承认的是,有了C# 3.0的自动属性,这件事并不难,但我讨厌定义那些只在一个地方使用的类型。如果用户可以传入有属性的任意对象,那为什么不让那些对象变成一个匿名类型呢?下面是最终代码:

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

哇,我们把用字典的五行代码缩至用对象初始化的两行代码(减去类型定义),甚至用匿名类型只要一行。

Bill想寻找更好的字典初始化器Alex在他的博文中用lambdas做了下,给了他很清晰的句法,PhilHa也开始想自己的办法。Bill说“你内心的Rubyist正在点头同意呢。”

Dictionary<string, object> items = Hash<object>(Name => "alex", TargetType => typeof(Uri), Id => 10);

Assert.AreEqual(10, items["Id"]);

如果你想做一些小的GUI应用,你得花点时间看下Ruby UI工具包的“Shoes”。为什么?如果你和我一样,是老的WinForms或者新接触WPF人群,(或者一个老Java使用者),这个工具包会对你有很大的帮助,告诉你一个UI域特定语言应该是什么样的。这里也有样本源代码

这里提供四个用四种语言的片段,展示一个按钮的点击事件如何显示消息。

在Shoes里也是一样。注意Shoes的文档是可得到的,但不够规范和统一。创建者不会在文档或者材料里使用缩写“GUI”,而是偏向于将Shoes看成是“toy”。真的挺像玩具的,看看这个二维动画示例吧

Shoes.app { button("Press Me") { alert("You pressed me") }}

Rob(和其他同行们)正在探索UserControl在ASP.NET MVC中会是什么样的。他说“你的UserControl可以是下列两者之一:可以在UI中显示通过Controller传递的信息 【或者】在UI中显示应用范围内的数据源。”他把它们叫做“Viewlet”,并提供了一些辅助函数:

呈现ViewUserControl

MVC工具包有一个叫做“RenderUserControl()”的函数,可以让你处理ViewUserControl,将结果inline

输出:

<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”)%>

如果ViewUserControl被写入(比如ViewUserControl<MyControllerData>),那么ViewData对象就会自动填充,然后你的ViewPage和生成的控件都会享有同样的数据。

如果你想明确实现这一功能,那你也可以这么做,指定要传递的数据:

<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”,ViewData.Users)%>

最后,如果你需要在ViewUserControl上设置属性,你也可以传入一个匿名类型:

<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”,ViewData.Users, new {GroupID=2})%>

希望你喜欢,继续阅读代码吧!

· 0 Comments