C# 如何解决通过管道传递所有对象输出的问题?

C# 如何解决通过管道传递所有对象输出的问题?,c#,powershell,C#,Powershell,我正在编写一个PowerShell模块,以利用C#中存储系统的API。我遇到了一个无法解决的问题。我有一个命令,可以将一个或多个对象通过管道传输到另一个对象,并且ProcessRecord()可以像您所期望的那样单独处理它们。但是,仅当我在第一个cmdlet中命名项,或在PowerShell中首先将其另存为变量时,才会出现这种情况 下面是我在PowerShell中执行此操作时看到的内容: PS C:\>$a=Show ISSFileSystem-Name fs1 PS C:\>$b=显示ISS文

我正在编写一个PowerShell模块,以利用C#中存储系统的API。我遇到了一个无法解决的问题。我有一个命令,可以将一个或多个对象通过管道传输到另一个对象,并且ProcessRecord()可以像您所期望的那样单独处理它们。但是,仅当我在第一个cmdlet中命名项,或在PowerShell中首先将其另存为变量时,才会出现这种情况

下面是我在PowerShell中执行此操作时看到的内容:

PS C:\>$a=Show ISSFileSystem-Name fs1
PS C:\>$b=显示ISS文件系统-名称fs1,cesSharedRoot
PS C:\>$C=Show ISSFileSystem包含上面列出的两个对象。
#类型
PS C:\>$a.Gettype().Fullname
ISS.FileSystemInfo.Filesystem
PS C:\>$b.Gettype().Fullname
系统对象[]
PS C:\>$C.Gettype().Fullname
ISS.FileSystemInfo.Filesystem[]
#引入第二命令
PS C:\>$a |显示ISSFileset#按预期返回
PS C:\>$b|显示ISSFileset#按预期返回
PS C:\>$C |显示ISSFileset#按预期返回
PS C:\>Show ISSFileSystem | Show ISSFileSet#失败,抱怨输入对象-自定义类(Filesystem)
Show ISSFileset:无法将输入对象绑定到命令的任何参数,因为该命令没有
不接受管道输入,或者输入及其属性与接受管道输入的任何参数都不匹配。
#计数对象
PS C:\>(Show ISSFileSystem-Name fs1 | Measure Object)。Count#按预期返回1
PS C:\>(Show ISSFileSystem-Name fs1,cesSharedRoot | Measure Object)。Count#按预期返回2
PS C:\>(Show ISSFileSystem | Measure Object).Count#返回1,即使变量有两个对象
PS C:\>($C | Measure Object).Count#首先保存到变量,上面的命令正确地返回预期的2。
如果有必要,我可以添加部分代码,但我只是想知道是否有人对这里可能发生的事情有任何快速的想法。它可以非常清楚地处理多个对象,但不能直接从第一个函数开始,除非我们指定一个(我使用的是ValueFromPipeline,而不是ValueFromPipelineByProperty)。有很多代码,我努力提供一个最小的例子

这就像第一个命令直接运行时将对象混合在一起,而第二个命令不知道输入是什么。有人有类似的问题吗

更新:

好的,所以我意识到输出中发生了一些奇怪的事情。在我从JSON转换响应之后,如果指定了Name参数,我将通过.Where()运行它,最终结果是一个对象列表。任何通过管道的东西都会出来并通过管道。如果未指定名称,则直接写入转换后的Json对象

不起作用:

//从Json转换
FileSystemInfo _convertJson=FileSystemInfo.FromJson(_响应);
//如果请求,请按名称筛选
if(Name!=null)
{
列出文件系统=_convertJson.FileSystems.Where(
f=>
Regex.IsMatch(f.Name.ToString(),
string.Format((?:{0})”,string.Join(“|”,Name))).ToList();
ForEach(WriteObject);
}
其他的
{
WriteObject(_convertJson.Filesystems);
}
作品:

//从Json转换
FileSystemInfo _convertJson=FileSystemInfo.FromJson(_响应);
//如果请求,请按名称筛选
if(Name!=null)
{
列出文件系统=_convertJson.FileSystems.Where(
f=>
Regex.IsMatch(f.Name.ToString(),
string.Format((?:{0})”,string.Join(“|”,Name))).ToList();
ForEach(WriteObject);
}
其他的
{
_convertJson.Filesystems.ToList().ForEach(WriteObject);
}
也许这不是最好的答案,有人可以纠正我。我才学了三个月

更新2:

非常感谢下面的PetAlSer和Mathias为我指明了正确的方向。上面的列表转换不是必需的,只需要将集合枚举为WriteObject的一部分,以便第二个cmdlet接收每个对象

WriteObject(_convertJson.Filesystems,true);

正如PetSerAl在评论中指出的那样:


这是核心PowerShell行为:当管道的第一个(或唯一一个)元素是表达式并且该表达式导致集合时,则枚举该集合,并通过管道而不是集合本身传递其内容

Cmdlet.WriteObject()
有一个函数,允许您指示管道处理器不要展开可枚举的输出,您可以使用
List.ForEach()
(假设
T
是可枚举的),但要有一点重复:

Action<object> WriteObjectWithoutEnumeration = 
    o => this.WriteObject(o, false);

FileSystems.ForEach(WriteObjectWithoutEnumeration);

// or, without ForEach:
WriteObject(_convertJson.Filesystems, false);
Action WriteObjectWithoutEnumeration=
o=>this.WriteObject(o,false);
ForEach(WriteObjectWithoutEnumeration);
//或者,没有ForEach:
WriteObject(_convertJson.Filesystems,false);

这是核心PowerShell行为:当管道的第一个(或唯一一个)元素是一个表达式,而该表达式导致集合时,该集合被枚举,其内容通过管道而不是集合本身传递。@mathias-r-jessen我想我在某个地方因为不完全清楚而把人们弄糊涂了,但我们已经找到了答案。今天早上我注意到WriteObject上的enumerateCollection bool,当我将其设置为true时,它的工作方式与我预期的一样,即第一个cmdlet中的所有对象都可以由第二个cmdlet处理。更新了我的问题。Thanks@Ash啊,我明白了,现在一切都变得更有意义了。在任何情况下,现在您至少知道如何控制这种行为:)是的,我想我只是在VisualStudio中没有注意到。再次感谢。请注意,
false
WriteObject
的第二个参数的默认值: