Как мне решить проблему с передачей всех объектов через конвейер? - PullRequest
0 голосов
/ 04 июля 2019

Я пишу модуль PowerShell для использования API для системы хранения в C #, и я столкнулся с проблемой, с которой не могу разобраться.У меня есть одна команда, которая может передать один или несколько объектов другому, и ProcessRecord () обрабатывает их все индивидуально, как и следовало ожидать.Однако это только когда я называю элементы в первом командлете или сначала сохраняю его как переменную в PowerShell.

Вот что я вижу в PowerShell, когда делаю это:

PS C:\> $a = Show-ISSFileSystem -Name fs1
PS C:\> $b = Show-ISSFileSystem -Name fs1,cesSharedRoot
PS C:\> $c = Show-ISSFileSystem    # Contains the two objects listed above.

# Types
PS C:\> $a.Gettype().Fullname
ISS.FileSystemInfo.Filesystem
PS C:\> $b.Gettype().Fullname
System.Object[]
PS C:\> $c.Gettype().Fullname
ISS.FileSystemInfo.Filesystem[]

# Introduce second command
PS C:\> $a | Show-ISSFileset                    # Returns as expected
PS C:\> $b | Show-ISSFileset                    # Returns as expected
PS C:\> $c | Show-ISSFileset                    # Returns as expected
PS C:\> Show-ISSFileSystem | Show-ISSFileSet    # Fails, complaining about the input object - Custom Class(Filesystem)

Show-ISSFileset : The input object cannot be bound to any parameters for the command either because the command does
not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

# Counting objects
PS C:\> (Show-ISSFileSystem -Name fs1 | Measure-Object).Count               # Returns 1 as expected
PS C:\> (Show-ISSFileSystem -Name fs1,cesSharedRoot | Measure-Object).Count # Returns 2 as expected
PS C:\> (Show-ISSFileSystem | Measure-Object).Count                         # Returns 1, even though the variable has two objects
PS C:\> ($c | Measure-Object).Count                                         # Saved to variable first, the command above correctly returns 2 as expected.

Я могу добавить части кода, если это необходимо, но я просто хотел узнать, есть ли у кого-нибудь быстрые мысли о том, что здесь может происходить.Он вполне может работать с несколькими объектами, но не напрямую из первой функции, если мы не назовем ее (я использовал ValueFromPipeline, а не ValueFromPipelineByProperty).В нем много кода, и я изо всех сил старался привести минимальный пример.

Это похоже на то, как первая команда объединяет объекты при непосредственном запуске, а вторая не знает, что представляет собой ввод.У кого-нибудь была похожая проблема?

ОБНОВЛЕНИЕ:

Хорошо, так что я понял, что с выходными данными происходит нечто странное.После того, как я преобразовал ответ из JSON, если был указан параметр Name, я пропустил его через .Where (), и конечным результатом стал список объектов.Все, что проходило через это, выходило и проходило через трубопровод, хорошо.Если имя не было указано, оно записывало преобразованный объект Json напрямую.

Не работало:

// Convert from Json
FileSystemInfo _convertJson = FileSystemInfo.FromJson(_response);

// Filter by name if requested
if (Name != null)
{
    List<Filesystem> FileSystems = _convertJson.Filesystems.Where(
        f =>
            Regex.IsMatch(f.Name.ToString(),
                string.Format("(?:{0})", string.Join("|", Name)))).ToList();
    FileSystems.ForEach(WriteObject);
}
else
{
    WriteObject(_convertJson.Filesystems);
}

Работает:

// Convert from Json
FileSystemInfo _convertJson = FileSystemInfo.FromJson(_response);

// Filter by name if requested
if (Name != null)
{
    List<Filesystem> FileSystems = _convertJson.Filesystems.Where(
        f =>
            Regex.IsMatch(f.Name.ToString(),
                string.Format("(?:{0})", string.Join("|", Name)))).ToList();
    FileSystems.ForEach(WriteObject);
}
else
{
    _convertJson.Filesystems.ToList().ForEach(WriteObject);
}

Возможно, это нене лучший ответ, и кто-то может исправить меня.Я изучал C # только три месяца.

UPDATE2:

Большое спасибо PetAlSer и Матиасу ниже, которые указали мне в правильном направлении.Преобразование списка, приведенное выше, не было необходимым, оно было необходимо только для перечисления коллекции как части WriteObject, чтобы второй командлет мог получать каждый объект.

WriteObject(_convertJson.Filesystems, true);

1 Ответ

1 голос
/ 05 июля 2019

Как уже отмечал PetSerAl в комментариях:

Это основное поведение PowerShell: когда первый (или единственный) элемент конвейера является выражением, и это выражение приводит к коллекции, тогда эта коллекция перечисляется и ее содержимое передается конвейером, а не самой коллекцией.

Cmdlet.WriteObject() имеет перегрузку , которая позволяет указывать процессору конвейера не развернуть перечисляемый вывод, который вы можете использовать с List<T>.ForEach() (при условии, что T перечислимо) с небольшим количеством карри:

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

FileSystems.ForEach(WriteObjectWithoutEnumeration);

// or, without ForEach:
WriteObject(_convertJson.Filesystems, false);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...