知识大全 G#语言简介
Posted 知
篇首语:落花踏尽游何处,笑入胡姬酒肆中。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 G#语言简介相关的知识,希望对你有一定的参考价值。
.NET家族新成员:G#语言简介 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
什么是G# G#是我在过去几个月里构思出来的一种新的程序设计语言 其目的是生成类型安全的代码 这些代码能够在编译时或运行时被注入(Inject)到一个代码基(Code Base)中 其语法是C# 的一个超集 和其他代码生成技术与工具(如CodeSmith 一种伟大的工具/语言)不同 G#并不打算生成用作起始点(Starting Point)或用于消费(Consumption)的代码 取而代之 G#使用了面向方面的程序设计(AOP)技术来向客户代码中注入代码 我们会快速地介绍一下AOP 因为它对很多开发者来说还是崭新的 AOP AOP或称面向方面的软件开发(AOSD)于 年在Xerox Parc创建 是一种相对先进的软件典范(Paradigm) 其思想很简单 通过使开发者每次只关注一个问题域来降低软件开发的复杂性 换句话说 人们在尝试解决一个业务问题(比如在互联网上销售产品)时无需考虑安全 线程 登录 数据访问和其他领域的问题 这被称为关注点的分离(Separation of Concerns) 通过分离这些领域或者方面 某一特殊方面的专家可以开发能够解决该方面问题的最好的解决方案 因此开发者无需再去掌握所有的行业 这样就有望产生健壮并且功能完善的软件 因为开发者只需做一名 软件问题域 的专家 AOP通过定义方面(也就是一组行为)来开始 然后将代码注入到适当的方法中去 每个代码注入点都被称作是一个结合点(Join Point) 让我们以安全为例 所有的输入都是邪恶的 是安全界的一条曼特罗(Mantra 咒语) 对抗这一难题的一种做法是 要求所有的开发者编写代码时都要在使用数据之前检查是否有恶意的输入 开发者们很可能会开发一个辅助方法用来解决这一问题 然后所有的开发者都会在他们的代码中简单地调用这个辅助方法 AOP可以解决这一问题 它抽取这些相同的辅助方法并创建一个方面 然后将其注入到需要对用户输入进行检查的地方 这个过程称为编排(Weaving) 我们没有简单地定义一个将会收到 邪恶输入 方面的位置列表 而是定义了将要使用的一组标准(Criteria) 既然是这样 我们就希望除方面之外能够注入所有带有参数的公共属性 方法和构造器 比起创建一个列表 这样做的好处是开发者们无需再凭借他们的记忆来将需要对输入进行检查的方法添加到列表中 相对于你所熟悉的AOP语言如ASPectJ G#并没有单独的编排文件 编排被集成到了语法当中 对于大多数程序员来说 别人可以将代码注入到他们的代码基之中 这无疑是一种容易引起恐慌的建议 为了解决这一问题 G#包含了一个用来处理这一问题的安全模型 并且允许程序员来控制哪些人可以注入代码以及可以注入什么样的代码 这将放在后面进行讨论 在我们深入之前先来看一些基础要素 基础
public class Client public Client() Messenger( Hello World ); private void Messenger(string message) Console WriteLine(message); public generator Rename static generation ChangeIt : target Client Messenger(string message) pre string oldMessage = message; message = Hello G# ; post message = oldMessage;
尽管这个例子没有任何用途 但它演示了G#的大量特性 首先 Client类使用了标准的C#语法——这在G#中是有效的 它只是简单地向控制台输出了消息 Hello World 这个类定义下面是G#中新增的语言构造 称作生成器(Generator) 现在只需认为生成器是所有用于定义 如何生成代码 的代码的容器即可 这和类(Class)类似 Rename是这个生成器的名字 就好像Client是类的名字一样 接下来定义了一个名为ChangeIt的生成(Generation) 生成和方法类似 每次调用它都会执行一些动作 不同的是在调用生成的时候会通常产生代码 注意ChangeIt有一个目标(Target) 在这里是来自Client类的Messenger方法 目标可以是任何(语言)构造 并且还可以包括通配符和正则表达式来指定一组项目作为目标 这表示由该生成所发出(Emit)的所有代码都将被注入到Messenger方法中 关键字pre规定了其后面花括号中定义的所有代码都将被注入到Messenger方法体中定义的代码之前 关键字post规定了其后面花括号中定义的所有代码都将被注入到Messenger方法体中定义的代码之后 因为用关键字static标记了这个生成 因此代码的实际注入是编译过程的一部分 理解这一点很重要 程序员将无法看到Messenger方法的变化 除非使用ildasm或Reflector来检查Messenger方法 此外还有一个目前还只是梦想的特性 就是能够生成动态的Region 这样在Visual 中就能打开它来检查生成器都在客户环境中生成了哪些代码 稍后我们将讨论其他类型的生成
private void Messenger(string message) // From ChangeIt pre block string oldMessage = message; // From ChangeIt pre block message = Hello G# ; // From the Messenger method body Console WriteLine(message); // From ChangIt post block message = oldMessage;
这个方法因此将向控制台打印 Hello G# 然后再将message字符串改回最初传入的消息 注意在 NET中字符串是不可变的 因此实际上是不能改变一个字符串所包含的内容的 因此通过在post块中将message改回初始的消息以保护Messenger方法外的 Hello World 消息并不是必须的 但是对于在Messenger方法体中执行的任何代码来说 后置的注入代码都是很重要的 这里出现的一个逻辑问题是 在后置条件(Post Condition)之后 Messenger方法体中的代码究竟什么时候执行呢?这个问题完美地引出了下一节
生成器的继承 我们上面的例子表明 生成器就是生成的包容器 但是其中还可以包含类能够包含的所有成员(如方法 属性 域 事件等等) 此外可见性和其他修饰符如virtual也可以用于生成 因此 生成器是面向对象的 并且可以彼此继承 这样做的原因和类类似 这允许基生成器定义一个基本的注入行为 并由子生成器定义更多的特殊的行为
public class Client protected string message; public Client() ssage = Hello World ; Messenger(ssage); private void Messenger(string message) onsole WriteLine(message); public generator Base protected virtual generation ChangeIt : target Client Messenger(*) pre string message = Hello G# ; post ssage = message; public generator Sub : Base protected override generation ChangeIt : target Client Messenger(string message) pre base pre(); message = ssage; post ssage = message; base Post();
下面给出了发出的Messenger方法 我们来分解一下这些代码 Sub生成器从Base生成器派生而来 并且重写了 基类 中的 方法 ChangeIt 基类 中使用星号(*)定义了一个目标 它可以被任何参数取代 这意味着它的目标可以是Client类中Messenger的所有重载形式 稍后我们将介绍定义目标的细节 凭经验就可以知道一个基本的规则是 在重写的生成中必须为目标指定更多的特性 在代码的另外一部分中 我们使用了关键字base来访问基生成器的pre和post 因此我们可以决定是在Base生成器发出代码之前还是之后发出Sub生成器的代码
private void Messenger(string message) // Base string ssage = Hello G# ; // Sub message = ssage; Console WriteLine(message); // Sub ssage = message; // Base ssage = ssage;
捕获 关键字capture用于引用在同一个生成的作用域中定义的变量 即使这个变量定义在基生成器中 能够访问这些变量的原因是 所有生成的代码都将位于相同的作用域中 在访问被捕获(Capture)的变量时 关键字capture并不是必需的 但这里的Messenger方法使用了同名的变量 在这种情况下 就需要关键字capture来解决混淆问题 变量message定义在Base生成器的ChangeIt生成中 而其目标Messenger方法中也有可能定义同名的参数 因为我们在定义中使用了星号(*)通配符 这种请况很可能发生 因为生成中可以定义局部变量 并且稍后在其目标方法的重载中也可以定义同名的局部变量 如果G#不对其采取行动的话 当目标方法中定义了和生成中的局部变量同名的变量时 就会引发一个编译错误 分节符 为了指出如何发出代码 G#提供了能够通过执行代码来取代发出代码 这通过 § 符号来实现 该符号称作分节符(Section Sign) 该符号在Times New Roman字体中是这样的 § 而在Courier New字体(译注 原文是Courier字体 这里为了同一代码格式使用了Courier New字体 两者非常相似)中是这样的 § 当在代码中放置了§的时候 其后的代码将被执行 而不是被发出
pre § for(int i = ; i < ; i++) § Console WriteLine(i); § 绿色高亮的代码在编译期间将被执行而不是被发出 从这个pre块发出的代码是这样的 Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); Console WriteLine( ); 注意当这几行代码被发出时 i 被它的整数值取代了 G#知道如何注入基本类型如int和float的值 但他无法发出类或其他自定义的复杂类型 如果§后跟了一个方法 该方法的返回值类型必须是基本类型 void或emit 如果是其他类型 则编译过程将会破坏返回的所有东西 我们将在下一节里解释关键字emit 我从来没有见过哪个键盘上有§符号 不过可以通过定义组合快捷键来产生这个符号 我选择 Ctrl+l (小写的L)来在Word里输出这个符号 并且在Visual 中为这个快捷键组合写了一个宏来输出这个符号
关键字emit 我们已经讨论了如何使用关键字pre和post来发出代码 但G#中有更丰富的方法来指定如何以及在哪里发出代码 其中一种方法就是像使用pre和post那样使用关键字emit
emit Console WriteLine( Hello G# );
代码 Console WriteLine( Hello G# ); 会在哪里发出?它将在其基生成的emit块中发出 [(That reminds be of the definition of a normal)]OK 那么pre和post实际上也是emit块 只不过它们定义了发出代码的位置(方法体的前面和方法体的后面) 对于上面的代码片断 我们需要提供一个上下文环境来说明一下这些代码是在哪里发出的
pre § Counter(); void Counter() emit Console WriteLine( The emit keyword in action );
当一个带有该pre块的生成被编译时 它会调用Counter方法 因为Counter()的前面有§符号 在Counter方法中 关键字emit用于注入对Console WriteLine的调用 emit块将会用块中的代码来取代对Counter()的调用 一个方法中emit块的数量没有任何限制 并且可以在emit块中使用§ 此外 emit只是对G#框架(G# Framework)中定义的Emit类型的一个映射 因此我们可以创建emit的实例
pre § DisplayParts(); public emit DisplayParts() emit partOne partTwo; partOne § Injector(partTwo); Console WriteLine( Part One ); § partTwo Emit(); return partOne Emit(); private void Injector(emit target) target Console WriteLine( Injection );
在上面的代码片断中 我们在DisplayParts生成的定义中创建了两个emit对象partOne和partTwo 然后我们使用partOne加花括号定义了一个emit块 花括号之间的所有代码都将被发出到partOne的局部存储(Local Store)中 当我们在partOne对象上调用Emit方法时 将会返回这个局部存储 最后 注意该代码段的pre块中调用了返回值类型为emt的DisplayParts [Since the emitted code is not caught it is emitted into the pre block ] 目标 我们已经探讨了当以一个方法为目标时如何使用关键字pre和post 但除此之外 G#还定义了一些关键字以使用其他语言构造作为目标 下面的表格给出了其他能够发出代码的关键字和它们的描述 为这些关键字指定目标构造时也可以使用通配符 参见后面的示例 关键字 描述 class 注入目标命名空间中所有的类 namespace 注入目标命名空间中所有的命名空间 set | get 注入目标所定义的所有set和get区域 generator 注入目标所定义的所有生成器 generation 注入目标所定义的所有生成 property 注入目标所定义的所有属性 method 注入目标所定义的所有方法
public generator Base protected virtual generation ChangeClient : target Client property public string * get post Console WriteLine(value); set pre Console WriteLine(value); method (public | protected) * Cl*(*) Console WriteLine( Cl* Method Targeted );
这里我们注入了所有类型为string而名字任意的属性 我们还在get访问器中使用了关键字value 该关键字在G#中表示由目标代码的get访问器所返回的值 在这里使用pre和post与在方法中的用法无异 接下来的关键字method定义了我们将要注入的所有公共的和受保护的方法 其中两个星号(*)分别表示返回值类型任意并且方法的名字是以 Cl 开头 后跟任意多个任意的字符 (译注 实际上是 个星号 后面括号里那个表示该方法能够带任意多的参数 )在名字中还可以使用 英镑($) 符号作为通配符 表示任意的一个字符 注意到这一点很重要 Client类中所有满足约束条件的成员都会被注入
自适应生成 第二种生成的类型是自适应生成(Adaptive Generation) 只是简单地把一个生成前面的关键字static换成adaptive 自适应生成在运行时生成并且注入代码 因此它可以检查对象的状态以指导生成 比起静态生成 自适应生成的优势在于第三方也可以提供生成框架和组件 第三方开发者可以通过创建幻象目标(Phantom Target)来以他们一无所知的代码基作为目标 幻象目标并不存在于生成框架或目标框架中 当开发者希望使用一个第三方的生成器时 他们可以加入幻象的命名空间 类 方法并将生成的代码重定位到他们的代码基中适当的位置
public class Client protected string message; public Client() ssage = Hello World ; Messenger(ssage); public string Message get return ssage; private void Messenger(string message) Console WriteLine(message); // Phantom Target namespace ThirdParty Security public adaptive generator Input : target Client
程序集
cha138/Article/program/net/201311/11918相关参考
MacromediaFlex标记语言简介 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!Macrom
Oracle数据库g消除了文件大小障碍随着越来越大的硬盘驱动器成为常见现象以及在位操作系统中提供对大文件(定义为大于GB)的支持今年还认为是很大的文件到明年可能就成了小文件有了Oracle数据库g
知识大全 严蔚敏《数据结构(c语言版)习题集》算法设计题第七章答案
第七章图 StatusBuild_AdjList(ALGraph&G)//输入有向图的顶点数边数顶点信息和边的信息建立邻接表 InitALGraph(G); scanf(%d
Java桌面应用程序设计:SWT简介 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Java语言
秘鲁斑[共鸟],[共鸟]形目(Tinamiformes)、[共鸟]科、斑[共鸟]属鸟类。分布在南美洲。鸟种简介中文名称:秘鲁斑[共鸟],[共鸟]读音gōng。拉丁学名:Nothoproctakalin
J2SE简介 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 多数编程语言都有预选编译好的类库以支
简单的说正则表达式是一种可以用于模式匹配和替换的强有力的工具我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影例如vi编辑器Perl或PHP脚本语言以及awk或sedshell程序等
灰黄唐加拉雀(学名:Tangarapalmeri,英文名:Grey-and-goldTanager)是裸鼻雀科唐加拉雀属的鸟类。中文学名:灰黄唐加拉雀拉丁学名:Tangarapalmeri英文俗名:G
岩鹪鹩的简介、简介、外形特征、地理分布、生活习性、生长繁殖、地理分布、保护现状
岩鹪鹩是一种小型鸣禽,身长12-15cm,翼展23cm,体重15-18g,寿命6年。鼻孔裸露被有鼻膜。翅短而圆,初级飞羽10枚。尾短小而柔软,尾羽12枚。跗蹠强健,具盾状鳞,趾及爪发达。羽被柔软厚密,
红斑吸蜜鹦鹉身长17公分(6.5吋),体重30-35g。这种鹦鹉鸟体为绿色,前额、头顶、尾巴内侧覆羽和胸部两侧均为红色;耳羽为蓝紫色,并带有亮丽的放射状条纹;尾羽红底,尾巴上方覆羽分布著不同程度的红色