关键字emit
我们已经讨论了如何使用关键字pre和post来发出代码,但G#中有更丰富的方法来指定如何以及在哪里发出代码。其中一种方法就是像使用pre和post那样使用关键字emit:
emit
{
Console.WriteLine(“Hello G#”);
}
...
pre
{
§ Counter();
}
...
void Counter()
{
emit
{
Console.WriteLine(“The emit keyword in action”);
}
}
此外,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...”);
}
}
目标
我们已经探讨了当以一个方法为目标时如何使用关键字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”);
}
}
}
自适应生成
第二种生成的类型是自适应生成(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);
}
}
}
}
现在的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
