我目前正在尝试使用PowerShell 3.0中引入的AST功能来修改ScriptBlock。我的要求是ScriptBlock的参数块中的所有参数都获得[Parameter(Mandatory)]
属性。
基本上代码应该修改它:
Param([string]$x)
Write-Host $x
到此:
Param([Parameter(Mandatory)][string]$x)
Write-Host $x
但是,我在添加新属性时遇到了问题,因为它需要IScriptExtent
而我不确定应该如何创建新的IScriptExtent
。
如何创建新的脚本范围?我可以使用什么价值的头寸?我是否必须更改所有后续范围的位置?
我尝试重新使用我正在修改的每个参数的范围,但不幸的是,这似乎没有产生应该的结果(例如,当我在修改后的ToString
上调用ScriptBlock
时我不知道看到任何变化。)
到目前为止,我的实施基于找到的ICustomAstVisitor
here。
最重要的方法如下:
public object VisitParameter(ParameterAst parameterAst)
{
var newName = VisitElement(parameterAst.Name);
var extent = // What to do here?
var mandatoryArg = new AttributeAst(extent, new ReflectionTypeName(typeof (ParameterAttribute)),
new ExpressionAst[0],
new[] {new NamedAttributeArgumentAst(extent, "Mandatory", new ConstantExpressionAst(extent, true), true)});
var newAttributes = new[] {mandatoryArg}.Concat(VisitElements(parameterAst.Attributes));
var newDefaultValue = VisitElement(parameterAst.DefaultValue);
return new ParameterAst(parameterAst.Extent, newName, newAttributes, newDefaultValue);
}
答案 0 :(得分:3)
以I
开头的名称通常是接口。它们不是您创建实例的类,它们是各种合同,指定特定类实现某些已知功能集。
例如,[hashtable]
实现IEnumerable
。这意味着任何知道如何使用IEnumerable
接口并在该类上运行的东西;你可以创建自己的实现接口的类,而且从来不知道关于你的类或它的作用的代码仍然可以以IEnumerable
定义的方式与它交互(在这种情况下,这是一种迭代的方式)在它上面。)
因此,当一个函数声明一个带有接口类型的参数时,它不会查找任何一个特定的类,它会查找实现该接口的任何类。
然后,下一步是找到实现该接口的类型。以下是我用过的一些PowerShell代码:
[System.AppDomain]::CurrentDomain.GetAssemblies().GetTypes() | Where-Object {
[System.Management.Automation.Language.IScriptExtent].IsAssignableFrom($_)
}
由此,我们可以看到以下内容:
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False IScriptExtent False False InternalScriptExtent System.Object False False EmptyScriptExtent System.Object True False ScriptExtent System.Object
第一个列表是界面本身。在其他三个中,其中两个不公开,所以只留下ScriptExtent
。
您可以使用New-Object
创建其中一个,但您需要将开始和结束位置作为[ScriptPosition]
个对象提供。如果没有看到更多代码,我就不能完全确定应该是什么。
答案 1 :(得分:3)
脚本范围主要用于错误报告,但也用于调试(例如,设置行断点。)
通常,合成脚本的选项(如您的示例)是:
在您的示例中,以上任何一种都是合适的。第二种选择是最简单的。第三个选项只是第二个选项的变体,但您可以将内容设置为有用的内容,例如
<#Generated: [Parameter(Mandatory)] #>