科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件.NET家族新成员:G#语言简介(3)

.NET家族新成员:G#语言简介(3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

G#是我在过去几个月里构思出来的一种新的程序设计语言。其目的是生成类型安全的代码

作者:lover_P编译 来源:blog 2007年11月4日

关键字: G#语言

  • 评论
  • 分享微博
  • 分享邮件
关键字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”开头、后跟任意多个任意的字符。(译注:实际上是3个星号,后面括号里那个表示该方法能够带任意多的参数。)在名字中还可以使用“英镑($)”符号作为通配符,表示任意的一个字符。注意到这一点很重要:Client类中所有满足约束条件的成员都会被注入。

  自适应生成

  第二种生成的类型是自适应生成(Adaptive Generation),只是简单地把一个生成前面的关键字static换成adaptive。自适应生成在运行时生成并且注入代码,因此它可以检查对象的状态以指导生成。

  比起静态生成,自适应生成的优势在于第三方也可以提供生成框架和组件。第三方开发者可以通过创建幻象目标(Phantom Target)来以他们一无所知的代码基作为目标。幻象目标并不存在于生成框架或目标框架中。当开发者希望使用一个第三方的生成器时,他们可以加入幻象的命名空间、类、方法并将生成的代码重定位到他们的代码基中适当的位置。 public class Client

{
 protected string message;
 public Client()
 {
  this.message = “Hello World”;
  Messenger(this.message);
 }
 
 public string Message
 {
  get
  {
   return this.message;
  }
 }

 private void Messenger(string message)
 {
  Console.WriteLine(message);
 }
}

// Phantom Target

namespace ThirdParty.Security
{
 public adaptive generator Input : target Client
 {}
}

  程序集:

// Third Party generator

public generator Security
{
 protected adaptive generation CheckInput
 : target ThirdParty.Security.Input
 {
  property public string *
  {
   get
   {
    pre
    {
     value = ValidateInput(value);
    }
   }
  }

  method public * *(all string *(input))
  {
   pre
   {
    input = ValidateInput(input);
   }
  }
 }
}

  在上面的代码中,我们定义了一个Client类、一个第三方生成器Security和一个幻象目标命名空间ThirdParty.Security。类和幻象目标被定义在一个程序集中,而第三方生成器在另外一个程序集中提供。第三方定义了所有类型为string的公共属性在返回之前都要调用ValidateInput方法。它还定义了所有返回值类型为string的公共方法在执行任何代码前都要对其类型为string的参数调用ValidateInput。G#中的关键字all表示对于作用域内所有符合标准的参数都要做这件事情。星号(*)表示参数的名字可以是任意的,我们必须将想要引用的实参的名字放在圆括号中,以告诉编译器我们正在使用这个名字,但我们不希望将它作为标准的一部分。

  现在的CLR能够在运行时动态地注入IL代码,这发生在程序集加载时,通过Profiler API完成。然而这种途径还存在着一系列的安全问题,因为它禁用了CAS,因此还需要深入的研究才能找到一种切实可行的解决方案。我们将在下面描述这是如何完成的。 CAS和注入特性
现在已经有望解决注入代码所引发的安全问题了。G#的安全模型能够确保只有你希望他注入代码的人才能注入代码,并且这些代码只能限制在你所允许的代码访问安全(CAS,Code Access Security)许可中。通过使用元数据,你可以声明你授予注入代码的权限。这仍需要定义一种语法并加入建议[Still need to define this syntax and open to suggestions.]。所有包含生成器和生成的程序集都必须被赋予一个强密钥,然后为目标程序集添加一个带有该公共密钥记号的Injector特性。只有在Injector中指出了强密钥的程序集才能运行和注入代码。

  总结

  代码生成为我们提供了各种可能性,我们希望G#能够发展成为一个泛型的、类型安全的代码生成语言。根据您的意见和建议,G#的语法还会改变并且进一步精炼,因此,非常感谢您阅读G#的相关文档,如果您有任何意见、问题或想法,请给Ernie Booth发email:gsharp@erniebooth.name。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章