2016-03-14 13 views
5

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

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

Write-Host $x 

しかし、私は問題に走ったと私はないです。これに

Param([string]$x) 

Write-Host $x 

を:

基本的にコードは、これを変更する必要がありますどのように新しいIScriptExtentを作成する必要がありますか?

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

私は変更している各パラメータの範囲を再利用しようとしましたが、残念ながらこれは結果をもたらすようには見えません(例えばを変更したScriptBlockに変更がありません)。

これまでの実装では、ICustomAstVisitorが見つかったhereに基づいています。

最も重要な方法は、次のようになります。Iで始まる

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); 
} 

答えて

3

名前は、通常のインタフェースです。それらは、インスタンスを作成するクラスではなく、特定のクラスが特定の既知の機能セットを実装することを指定するコントラクトです。

たとえば、[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]オブジェクトとして指定する必要があります。私は、あなたのコードの多くを見ることなく、それらが何であるべきかについて完全にはわかっていません。(。行ブレークポイントの設定、たとえば)

+0

私はインターフェイスが何であるかを知って、私の質問は非常に新しいコードを作成するときに(人がコードを変更し、エクステントを再利用するたくさんの例があるエクステントは、PowerShellで働く方法を把握することができない私の周りを公転するが、私人々が新しいコードを作成した例は見つかりませんでした)。 – chrischu

+1

@chrischu新しいIScriptExtentの作成方法を尋ねてきたので、インターフェイスに精通しているということはあなたの疑問からはっきりしないので、安全面で間違いを犯して説明するのが最善だと感じました。あなたの質問を見つける他の訪問者は、インターフェイスが何であるか知っていません。これまでに試したことをあなたの質問に含めることを検討することもできます。 – briantist

3

スクリプトの程度はエラー報告のために主に使用されますが、デバッグのために使用される一般的に

、(あなたの例のように)合成されたスクリプトのオプションは次のとおりです。

  • 再利用あなたは
  • 合成を作成します(基本的にはファイル、空行でScriptExtentとScriptPositionのインスタンスを作成します)、空のASTを使用
  • を追加しているASTに関連し、おそらく近い既存のAST、/デバッグに何らかの特別なコンテンツを使用している可能性があります。

この例では、上記のいずれかが適切です。 2番目のオプションは最も簡単です。 3番目のオプションは、2番目のオプションの変形ですが、内容を便利なものに設定します。

<#Generated: [Parameter(Mandatory)] #> 
+0

興味深い。私が持っている問題は1つありますが、変更されたASTのToString()を呼び出すと古いコードが返され、私の考えは古いエクステントのために起こるということでした。 ASTを正しいエクステントに依存しないソースコードに戻すもう1つの良い方法はありますか? – chrischu

+0

それほど簡単ではありません - かなりのプリンタは、Astに基づいて実装するのは完全に合理的なものですが、私はずっと前に書いたサンプルコード以外に、実際にはうまくいきませんフォーマット。 –

+2

「かなりのプリンタ」は全体の問題です。私はコードがきれいである必要はなく、ASTを修正した後にコードを取得するだけです。これは「正しい」エクステントを指定しないと動作しません。 ASTで手を動かすのではなく、文字列の変更を使ってコードを修正するほうがずっと簡単なようです。 – chrischu

関連する問題