Script#

原文地址:
http://www.nikhilk.net/ScriptSharpIntro.aspx

Script#原型
Script#把C#开发者的体验(编程和工具)带到JavaScript/Ajax世界.这篇帖子分享一个通过C#创建脚本的原型工程。
Script#把C#开发者的体验(编程和工具)带到JavaScript/Ajax世界.Yep,我最终公布了一段时间以来利用业余时间做的项目。
一个更好的写脚本的环境
这个工程的最根本的目标是提高脚本的技术发展水平。这个做法超出了惯例,我最初的想法是:编译时检查和智能感应或者自动语句完成,我确实认为这是非常有用的东东,并且他们本身也是很有价值的,当我们在Atlas上工作时也想像一种好的工具体验,为此尝试了不同的方法和技术,Script#就是这些探索中的一个原型,它尝试达到一些编程环境的要求:
1.一个具有天然结构的纯粹的语言。今天用脚本,可以在模拟OOP(类,接口和继承等)方面走得很远,但这些往往被开发者抛弃。各种各样的C#结构属性,事件,和定义继承的语法这些使代码更加可读。类似的修饰符public vs. protected vs. internal, sealed vs. virtual 等可以帮助建立更好的对象模型,所有的这些都可以带入到脚本世界。
2.更容易的Refactoring和exploration(译注:其实翻译成重构和导航没什么不好,Refactoring的英文解释是Refactoring is a program transformations that reorganize a program without changing its behavior,不过像这种通用词语还是不翻译吧,免得产生歧义)。脚本开发可以从Refactoring和在IDE以及.NET Reflector中支持的类浏览功能中受益匪浅,这两个东东会使代码便于管理。
3.产生文档的能力。同样C#的文档功能已经存在的基础架构将会大有裨益。
4.更加容易地定制脚本代码。比如,创建Dubug和Release最小版本。相同的主意可以用在创建一个用于诊断的脚本版本,该版本包含更多的错误检测和日志功能。这种方法可以用来包含用于探查和测试代码覆盖度的工具。另外这个项目可以产生出不同版本的脚本来适应JavaScript的当前版本,以及将来的JavaScript2.
示例
我将采用Ajax经典的Hello World来阐述这个模型。假设一个简单的页面,包含textbox, button 和label。

None.gif < input  type ="text"  id ="nameTextBox"   />
None.gif
< input  type ="button"  id ="okButton"  value ="OK"   />
None.gif
< span  id ="helloLabel" ></ span >
None.gif

现在我想写一些脚本给这个页面加一些UI逻辑。创建一个HelloWorld.CS文件,提取在Text中输入的值,用XMLHttp发出一个请求,最后在Label中显示结果。

None.gif using  System;
None.gif
using  ScriptFX;
None.gif
using  ScriptFX.UI;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
namespace  HelloWorld  dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public class HelloWorldScriptlet : IScriptlet dot.gif{
InBlock.gif
InBlock.gif        
private Button _okButton;
InBlock.gif        
private TextBox _nameTextBox;
InBlock.gif        
private Label _helloLabel;
InBlock.gif
InBlock.gif        
private XMLHttpRequest _request;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public void Start() dot.gif{
InBlock.gif            _okButton 
= new Button(Document.GetElementById("okButton"));
InBlock.gif            _nameTextBox 
= new TextBox(Document.GetElementById("nameTextBox"));
InBlock.gif            _helloLabel 
= new Label(Document.GetElementById("helloLabel"));
InBlock.gif
InBlock.gif            _okButton.Click 
+= new EventHandler(OnOKButtonClick);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private void OnOKButtonClick(object sender, EventArgs e) dot.gif{
InBlock.gif            Callback completedCallback 
= new Callback(this.OnRequestComplete);
InBlock.gif
InBlock.gif            _request 
= new XMLHttpRequest();
InBlock.gif            _request.Onreadystatechange 
= Delegate.Unwrap(completedCallback);
ExpandedSubBlockStart.gifContractedSubBlock.gif            _request.Open(
"GET""Hello.axd?name=" + _nameTextBox.Text, /**//* async */ true);
InBlock.gif            _request.Send(
null);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
private void OnRequestComplete() dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (_request.ReadyState == 4dot.gif{
InBlock.gif                _request.Onreadystatechange 
= null;
InBlock.gif
InBlock.gif                
string greeting = _request.ResponseText;
InBlock.gif                _helloLabel.Text 
= greeting;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif

这段代码显示了极其简单的HelloWorldScriptlet 类,用C#来写是一件非常愉悦的事情,现在是体验Script#魔力的时刻了。

None.gif ssc  / ref :sscorlib.dll  / ref :Script.ScriptFX.Core.dll  / debug  / out :HelloWorld.js HelloWorld.cs
None.gif

运行Script#的编译器(SCS.exe),产生如下所示的HelloWorld.js 文件:

None.gif Type.registerNamespace('HelloWorld');
None.gif
None.gif
// //
None.gif//
 HelloWorld.HelloWorldScriptlet
None.gif

ExpandedBlockStart.gifContractedBlock.gifHelloWorld.HelloWorldScriptlet 
=   function  Scenarios_HelloWorldScriptlet()  dot.gif {
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gifHelloWorld.HelloWorldScriptlet.prototype 
=   dot.gif {
InBlock.gif    _okButton: 
null,
InBlock.gif    _nameTextBox: 
null,
InBlock.gif    _helloLabel: 
null,
InBlock.gif    _request: 
null,
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    start: 
function Scenarios_HelloWorldScriptlet$start() dot.gif{
InBlock.gif        
this._okButton = new ScriptFX.UI.Button(document.getElementById('okButton'));
InBlock.gif        
this._nameTextBox = new ScriptFX.UI.TextBox(document.getElementById('nameTextBox'));
InBlock.gif        
this._helloLabel = new ScriptFX.UI.Label(document.getElementById('helloLabel'));
InBlock.gif        
this._okButton.add_click(new Delegate(thisthis._onOKButtonClick));
ExpandedSubBlockEnd.gif    }
,
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    _onOKButtonClick: 
function Scenarios_HelloWorldScriptlet$_onOKButtonClick(sender, e) dot.gif{
InBlock.gif        
var completedCallback = new Delegate(thisthis._onRequestComplete);
InBlock.gif        
this._request = new XMLHttpRequest();
InBlock.gif        
this._request.onreadystatechange = Delegate.unwrap(completedCallback);
InBlock.gif        
this._request.open('GET', 'Hello.axd?name=+ this._nameTextBox.get_text(), true);
InBlock.gif        
this._request.send(null);
ExpandedSubBlockEnd.gif    }
,
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    _onRequestComplete: 
function Scenarios_HelloWorldScriptlet$_onRequestComplete() dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (this._request.readyState == 4dot.gif{
InBlock.gif            
this._request.onreadystatechange = null;
InBlock.gif            
var greeting = this._request.responseText;
InBlock.gif            
this._helloLabel.set_text(greeting);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gifHelloWorld.HelloWorldScriptlet.registerClass('HelloWorld.HelloWorldScriptlet', 
null , ScriptFX.IScriptlet);
None.gif

注意一个类是如何转换成JavaScript等价物的:一个函数和原型上的方法。更进一步,注意如何自动产生调用以便将函数注册作为类。编译器提供一个良好的自然模型来声明继承体系。其他需要一提的是JavaScript如何模拟C#中的事件和属性访问。基本上,让编译器去做脏活累活,你自己不用去费神劳力地去做OOP的模拟。最后,既然使用了/debug编译选项,它为每个方法提供了一个名字(debugger时不能用匿名方法)这个也是自动产生的。一个简单的例子不能讲清楚它的转换能力,需要展示更多的内容。
产生的代码可以包含在通常的<script>标签中使用了。

None.gif < script type = " text/javascript "  src = " sscorlib.js " ></ script >
None.gif
< script type = " text/javascript "  src = " ssfxcore.js " ></ script >
None.gif
< script type = " text/javascript "  src = " HelloWorld.js " ></ script >
None.gif
< script type = " text/javascript " >
None.gifScriptFX.Application.Current.run(
new  HelloWorld.HelloWorldScriptlet());
None.gif
</ script >
None.gif

Script#可以生成一个包含.JS文件作为资源的Assembly,这样联合服务器控件可以使用ASP.NET的WebResources属性以一种简单的方式在页面中包含脚本。

None.gif ssc  / ref :sscorlib.dll  / ref :Script.ScriptFX.Core.dll  / debug  / assembly:HelloWorld.dll  / out :HelloWorld.js HelloWorld.cs
None.gif
None.gif
< nStuff:Scriptlet runat = " server "
None.gif    ScriptAssembly
= " HelloWorld "  ScriptletType = " HelloWorld.HelloWorldScriptlet "   />
None.gif
None.gif

编译器有debug和release的概念,

None.gif ssc  / ref :sscorlib.dll  / ref :Script.ScriptFX.Core.dll  / minimize  / out :HelloWorld.js HelloWorld.cs
None.gif

用/minimize参数替代/debug将会生成Release版本,如下所示(为了显示我故意增加了一些线)

None.gif Type.registerNamespace('HelloWorld');
ExpandedBlockStart.gifContractedBlock.gifHelloWorld.HelloWorldScriptlet
= function () dot.gif {}
ExpandedBlockStart.gifContractedBlock.gifHelloWorld.HelloWorldScriptlet.prototype
= dot.gif {$0:null,$1:null,$2:null,$3:null,
ExpandedSubBlockStart.gifContractedSubBlock.gifstart:
function()dot.gif{
InBlock.gif
this.$0=new ScriptFX.UI.Button(document.getElementById('okButton'));
InBlock.gif
this.$1=new ScriptFX.UI.TextBox(document.getElementById('nameTextBox'));
InBlock.gif
this.$2=new ScriptFX.UI.Label(document.getElementById('helloLabel'));
ExpandedSubBlockEnd.gif
this.$0.add_click(new Delegate(this,this.$4));}
,
ExpandedSubBlockStart.gifContractedSubBlock.gif$
4:function(sender,e)dot.gif{
InBlock.gif
var $2=new Delegate(this,this.$5);
InBlock.gif
this.$3=new XMLHttpRequest();
InBlock.gif
this.$3.onreadystatechange=Delegate.unwrap($2);
InBlock.gif
this.$3.open('GET','Hello.axd?name='+this.$1.get_text(),true);
ExpandedSubBlockEnd.gif
this.$3.send(null);}
,
ExpandedSubBlockStart.gifContractedSubBlock.gif$
5:function()dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(this.$3.readyState==4)dot.gif{
InBlock.gif
this.$3.onreadystatechange=null;
InBlock.gif
var $0=this.$3.responseText;
ExpandedBlockEnd.gif
this.$2.set_text($0);}
}
}

None.gifHelloWorld.HelloWorldScriptlet.registerClass('HelloWorld.HelloWorldScriptlet',
null ,ScriptFX.IScriptlet);
None.gif

正如你看到的,所有无关紧要的空格都被去掉了,并且标识符都是尽可能的小(这个对脚本的最小化贡献最大)用$0,$1等来表示,最令人激动的是Script#编译器可以利用C#代码中的信息最大限度地使代码最小化。这些内容包括哪些成员是internal/private,哪些成员是public的,比如类中的_okButton现在是$0,OnRequestComplete 方法现在是$5.
除了用一个聪明的方式产生脚本外,Script#也用IDE增强了脚本的创建。尽管已经用DOM写了几个月的程序,我还是要一直把MSDN打开查看有关DOM的参考资料,用Script#可以做到如下的样子:
Intellisense1.jpg
Intellisense2.jpg

应该关注的是智能感应和语句的自动完成以及C#编辑器提供的一些工具。它们反射sscorlib 这个工程采用了这种机制。
基本上我已经介绍了Script#的术语,以及编译的目标文件和与VS2005编程体验的整合,编译可以生成.dll文件和.JS文件,可以部署到你的工程当中。
原理
从本质上来说,Script#编译器是一个C#编译器,只不过生成的是JavsScript而不是IL。最主要的目标是产生可读的JavaScript脚本,这些脚本你自己也可以手动创建,并且可以将其部署到实际的应用当中。因此这个转换是C#级别的,而不是从IL转化成脚本,这个转换本身并不会增加任何抽象。
C#中的一些东西没有意义(比如lock,Unsafe)还有一些东西目前我不支持(比如范型)。这个转换器支持C#主要东东,比如foreach,委托以及debug条件编译。相关的类库(sscorlib,mscorlib的等价物)也被转化成JavaScript.它跟mscorlib包含的东东不同。我采用的方式不是写一个转化器,将任意用C#写得应用转化成JavaScript类似于Winform的抽象层。相反,正如Atlas,Script#是提供一个引擎和高级的环境,在这个环境下可以用Htlm/Css,JavaScript以一种更加高效,稳定和可维护的方式开发应用。
还有少部分JavaScript的东东(特别是闭包以及更多功能风格的编程)在这个转化器中不被支持。我想一定会有可选的等价物,但我更有兴趣等待反馈。这种实现允许手动写JavaScript并以Assembly元数据的方式暴露给C#。这为与已经存在的代码交互提供了良好的解决方案,并给一些需要手动调整的东东提供了机会,我会在后面的帖子中继续论述。
一些历史介绍和可下载的东东
很多人想知道我们在Atlas应用的基于OOP的类型系统是否是在浏览器中基于C#开发的先驱,现在我将正面回答这个问题。用C#创建脚本的想法在我们开始积极写脚本的时候就有了,我错过了一切,因为我认为C#实现这些是理所当然的(译注:不会是怪俺的偶像Anders没提供这个功能吧?呵呵)12月假期的时候,我最终决定认真考虑写一个编译器来实现这个功能。
从那开始,工作进入下一个阶段,已经可以用来生成有用的脚本。就在上个星期我打算写一个帖子宣布这件事情。非常巧合的是,Google的伙计们也想到了类似的东东,我想我应该提前一些日子写这个帖子的:)不管怎么样,俺已经有了一个初步的发布版本。你可以下载Script#的编译器和例子。注意这只是一个很弱弱的版本(如果你想试用的话,请先确保你的代码可以作为C#的代码编译)。俺需要更多的事情来让它变得强一些,更好地与Web工程整合,并且简化一些关键的C#场景。这个可能需要蛮多的时间,因为这只是一个业余时间的原型,同时,这个下载会给你一些体验,俺期待反馈,请多多评注。
脚本挑战和下一个版本
最近我对浏览器和脚本世界写了一个期望列表,我希望阐述从一个全面的视角看相关的和一起到来的东东,到今天为止,转换的结果还是脚本。仍然有很多没有解决的东东,这些受限于浏览器的运行环境以及不同浏览器之间的差异等等。另外,基于转换的模式给调试带来了麻烦。就目前来说,Script#提供了一个方便的创建脚本的手段,我们希望能够提供一个伟大的工具和平台可以直接处理原生(native)脚本,如今天Atlas中存在的东东一样。长期来看,真正的胖Web应用的解决方案是与WPF/E(正像MIX06展示的那样)的结合,并且跨平台的CLR可以作为宿主在浏览器中直接创建和执行托管代码从而充分从这种模型中受益。
 

转载于:https://www.cnblogs.com/Farseer1215/archive/2006/06/09/421719.html

对以下标号标出的四个问题分别作答:1.请举例说明,文件夹的rwx权限的含义。 2.如果对于helloworld文件建立了其硬链接h_link和软链接s_link,此时如果(1)将helloworld文件重命名,是否可以依然正确读取h_link 与s_link;(2)将helloworld修改权限为333,是否可以读取h_link与s_link的内容;(3)将helloworld删除,是否可以正确读取h_link 与s_link;(4)重新创建一个名为helloworld的文件,此时修改其内容,是否会影响到h_link与s_link。3. 对一个文件file_permission,其初始权限为-rw-r--r--。如何使用chmod以将其所有者设置为可读可写可执行,所有组和其他设置为可写不可读权限。 4.在root用户的家目录中,编辑其.bash_profile文件,添加file_var0="file value 0"export FILE_ENV_VAR0="file environment value 0"保存退出后重新登录系统,使用env命令是否可以查到变量file_var0的值?是否可以查到FILE_ENV_VAR0的值?使用set命令呢?同时对如下脚本:#!/bin/bash# filename variable-script.shecho "var0=$var0"echo "env_var0=$env_ar0"echo "file_var0=$file_var0"echo "FILE_ENV_VAR0=$FILE_ENV_VAR0"按照给定顺序执行后,可获得何种结果?var0="value 0"export env_var0="export value 0"/bin/bash variable-script.sh# first time output from the script#blablablasource variable-script.sh# second time output from the script#blablablachmod u+x variable-script.sh./variable-script.sh# third time output from the script#blablabla
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值