3

假设我有这样的父子关系的对象:

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

现在,我想创建一个支持如下语法的 cmdlet:

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 属性能够像真正的 Node 对象一样引用管道中的另一个对象。

[编辑] 此错误是由类定义中缺少 public 关键字引起的。添加关键字解决了问题并使示例工作。

4

1 回答 1

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.Diagnostic.ProcessModule)之前存储了 System.Diagnostics.Process 对象的名称。然后我可以将隐藏的进程名称与模块的名称结合起来以产生我想要的输出。

上述方法适用于教学目的,但并不是真正的规范 PowerShell。这将是在 PowerShell 中执行此操作的更典型方法:

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

在这个场景中,我们采用了 Process 的名称并将其投影到每个 ProcessModule 对象中。请注意,当您尝试枚举其模块集合时,某些进程会产生错误。

于 2012-08-04T16:44:39.537 回答