2012-08-03 132 views
3

假設我有一個有這樣的父子關係的對象:導航父子關係

public class Node 
{ 
    public string Name { get; set; } 
    public string Type { get; set; } 
    public Node Parent { get; set; } 
} 

現在,我想創建一個支持語法像這樣的小命令:

Get-Node | where {$_.Type -eq "SomeType" -and $_.Parent.Name -eq "SomeName" } 

在這裏,Parent屬性需要以某種方式引用管道中的另一個對象。在PowerShell中甚至可以這樣做嗎?如果不是,有什麼選擇?

[編輯] 如果我使用上面這樣的類:

var root = new Node 
{ 
    Name = "root", 
    Type = "root", 
    Parent = null 
}; 
var nodeA = new Node 
{ 
    Name = "A", 
    Type = "node", 
    Parent = root 
} 
WriteObject(root); 
WriteObject(nodeA); 

,然後加載模塊,並嘗試這個命令:

Get-MyNode | where {$_.Parent.Name = "root"} 

我得到這個錯誤:

Property 'Name' cannot be found on this object; make sure it exists and is settable. 
At line:1 char:31 
+ Get-MyNode | where {$_.Parent. <<<< Name = "root"} 
    + CategoryInfo   : InvalidOperation: (Name:String) [], RuntimeException 
    + FullyQualifiedErrorId : PropertyNotFound 

我希望Parent屬性在管道中引用另一個對象,如真實節點對象。

[編輯]此錯誤是由類定義中缺少public關鍵字引起的。添加關鍵字解決了問題,並使示例工作。

+0

你能更具體嗎?我不明白你的意思是「另一個對象」。你有C#和PowerShell的僞代碼,但它們之間的聯繫是微不足道的。 – x0n 2012-08-04 13:52:49

+0

我對PowerShell很新,所以請耐心等待。如果我使用Write對象方法將父引用指向另一個節點,那麼會發生什麼?管道中的對象將有一個名爲Parent的屬性。我能像上面那樣在一個Where-Object語句中使用它嗎? – MvdD 2012-08-06 04:36:57

+0

在上面的代碼示例中,Node類是內部的,因爲它缺少了public修飾符。這可能會使事情複雜化;) – x0n 2012-08-06 17:53:35

回答

2

我希望你的Get-Node cmdlet能夠返回一個完全填充的對象圖。下面是這個使用XML的一個類似的例子:

$xml = [xml]@' 
<?xml version="1.0" encoding="ISO-8859-1"?> 
<bookstore> 
    <book> 
     <title lang="eng">Harry Potter</title> 
     <price>29.99</price> 
    </book> 
    <book> 
     <title lang="eng">Learning XML</title> 
     <price>39.95</price> 
    </book> 
</bookstore> 
'@ 

$xml.SelectNodes('//*') | Where {$_.ParentNode.Name -eq 'book'} 

在回答你關於在管道中訪問其他對象的問題,這種情況並不少見創建中間變量作爲管道的一部分,以後可以參考:

Get-Process | Foreach {$processName = $_.Name; $_.Modules} | 
       Foreach {"$processName loaded $($_.ModuleName)"} 

在這種情況下,我將System.Diagnostics.Process對象的名稱存儲在管道即System.Diagnostic.ProcessModule之前,然後再傳遞一個完全不同的類型。然後,我可以將隱藏的進程名稱與模塊的名稱結合起來以生成我想要的輸出。

上述方法對於教學目的是有好處的,但並不是真正規範的PowerShell。這將是在PowerShell中這樣做更典型的方式:

Get-Process | Select Name -Exp Modules | Foreach {"$($_.Name) loaded $($_.ModuleName)"} 

在這種情況下,我們已經採取了過程的名稱和它投射到每個ProcessModule對象。 請注意,當您嘗試枚舉其模塊集合時,某些進程將生成錯誤。

+0

好吧,這意味着我需要創建一個名爲'NodeTree'的類,我將寫入管道並在該NodeTree類上定義一個SelectNodes方法。它不適用於Where-Object子句,對吧?我不確定管道中的中間對象會對此有所幫助,但很高興知道這是可能的。 – MvdD 2012-08-06 04:38:21

+0

@ user18044在上面的第一個示例中,我同時使用了'SelectNodes()'和'Where-Object' cmdlet。 – 2012-08-06 20:28:23

+0

你是對的。我錯過了x0n指出的public修飾符。 – MvdD 2012-08-19 22:54:11