5

現在、PowerShell 3.0 で導入された AST 機能を使用して ScriptBlock を変更しようとしています。私の要件は、ScriptBlock のパラメーター ブロック内のすべてのパラメーターが[Parameter(Mandatory)]属性を取得することです。

基本的に、コードはこれを変更する必要があります。

Param([string]$x)

Write-Host $x

これに:

Param([Parameter(Mandatory)][string]$x)

Write-Host $x

ただし、その新しい属性を追加するときに問題が発生しましIScriptExtentIScriptExtent

新しいスクリプト エクステントを作成するにはどうすればよいですか? 位置にはどのような値を使用できますか? 後続のすべてのエクステントの位置を変更する必要がありますか?

変更している各パラメーターの範囲を再利用しようとしましたが、残念ながら、これは必要な結果をもたらさないようです (たとえば、変更されたパラメーターを呼び出し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);
}
4

2 に答える 2

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                                               

最初のリストはインターフェース自体です。残りの 3 つのうち 2 つが公開されていないため、そのまま残しScriptExtentます。

これらのいずれかを作成できますがNew-Object、開始位置と終了位置を[ScriptPosition]オブジェクトとして指定する必要があります。あなたのコードをもっと見ないと、それらがどうあるべきか完全にはわかりません。

于 2016-03-14T18:34:16.183 に答える