Модуль C # PowerShell, преобразующий PSObject в класс C # - PullRequest
0 голосов
/ 05 декабря 2018

Я пишу свой первый PS-модуль на C # за последние несколько дней, и это очень ново для меня.У меня были некоторые проблемы с этим, если честно (возможно, не хватает кофеина), но сейчас я нашел решение, но надеюсь, что у кого-то могут быть более изящные идеи?

Я нахожу некоторыедокументации относительно powershell, чтобы быть немного расплывчатым, по крайней мере, в отношении создания модулей в C #.Внедрение C # в PowerShell, нет проблем, запуск кода PowerShell в C #, также много информации, но информация о написании модулей PS в C # кажется скудной, или я смотрю в неправильных местах?

Достаточно болтовни, вотмоя ситуация.Во-первых, у меня есть быстрый и грязный новый пример, и я получаю образец командлета ниже.

[Cmdlet(VerbsCommon.New, "TestItem")]
[OutputType(typeof(TestItem))]
public class NewItem : Cmdlet
{
    [Parameter(Position = 0)]
    public string FriendlyName
    {
        get { return friendlyname; }
        set { friendlyname = value; }
    }
    private string friendlyname;

    [Parameter(Position = 1)]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    private string name;

    [Parameter(Position = 2)]
    public int ID
    {
        get { return id; }
        set { id = value; }
    }
    private int id;

    private TestItem item;

    protected override void BeginProcessing()
    {
        item = new TestItem();
    }

    protected override void ProcessRecord()
    {
        item.Name = name;
        item.FriendlyName = friendlyname;
        item.ID = id;
    }

    protected override void EndProcessing()
    {
        WriteObject(item);
    }
}

[Cmdlet(VerbsCommon.Get, "TestItem")]
[OutputType(typeof(TestItem))]
public class GetItem : Cmdlet
{
    [Parameter(Position = 0)]
    public string[] FriendlyName
    {
        get { return friendlyname; }
        set { friendlyname = value; }
    }
    private string[] friendlyname;

    [Parameter(Position = 1)]
    public List<TestItem> Item { get; set; }

    [Parameter(ValueFromPipeline = true)]
    public PSObject InputObject
    {
        set { inputObject = value; }
        get { return inputObject; }
    }
    private PSObject inputObject;

    private List<TestItem> item;

    protected override void BeginProcessing()
    {
        item = new List<TestItem>();
    }

    protected override void ProcessRecord()
    {
        WriteVerbose("processing pipline");

        if (inputObject != null)
        {
            WriteObject(inputObject.ToClassObject<TestItem>());
        }
    }

    protected override void EndProcessing()
    {
        WriteObject(item);
    }
}

Затем у меня есть мой быстрый и грязный образец класса объекта

public class TestItem
{
    public TestItem()
    { }

    public string Name { get; set; }
    public string FriendlyName { get; set; }
    public int ID { get; set; }
}

И вот теперь яищу отзывы.Из приведенного выше видно, что новый элемент создает элемент, а когда он передается в get-item через конвейер, он передается как PSObject.Моя цель - превратить его обратно в объект класса, с которого он был запущен, но мне нужно иметь возможность динамически обрабатывать класс / тип, поскольку я собираюсь использовать его в качестве помощника для проекта, над которым я работаю.Я действительно просто жду отзывов, потому что чувствую, что здесь есть более элегантное решение?

public static class Helper
    {
        public static T ToClassObject<T>(this PSObject pso) where T : class, new()
        {
            try
            {
                T obj = new T();
                foreach (PSPropertyInfo psPropertyInfo in pso.Properties)
                {
                    foreach (var prop in obj.GetType().GetProperties())
                    {
                        try
                        {
                            if (psPropertyInfo.Name == prop.Name)
                            {
                                PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                                propertyInfo.SetValue(obj, Convert.ChangeType(psPropertyInfo.Value, propertyInfo.PropertyType), null);
                            }
                        }
                        catch
                        {
                            continue;
                        }
                    }

                }

                return obj;
            }
            catch
            {
                return null;
            }
        }
    }

1 Ответ

0 голосов
/ 05 декабря 2018

Хорошо, то, над чем вы работаете, называется бинарными модулями / двоичными командлетами, что, вероятно, слово для поиска в Google (это дает мне много статей об этом).Вы также можете найти несколько примеров из реальной жизни на github Powershell Core, например здесь .С другой стороны, кажется, что это не очень распространенный способ создания командлетов для powershell, и, на мой взгляд, он намного сложнее, чем чистый код PS.

Что касается вашего вопроса, насколько я понимаю, вашКомандлет Get-Item получает PSObject из конвейера, и вам необходимо преобразовать его в пользовательский тип, используя имена входных свойств.Если это так, вы, вероятно, можете использовать свойство ValueFromPipelineByPropertyName вместо ToClassObject.Я не являюсь экспертом в написании C # или бинарных модулей, поэтому я приведу свой пример на чистом PS, я надеюсь, что это не большая проблема, чтобы преобразовать его в C #

function Get-Column { [CmdletBinding()]param(
    [parameter(ValueFromPipelineByPropertyName=$true)][String]$columnName,
    [parameter(ValueFromPipelineByPropertyName=$true)][String]$type
    )

    Process { Write-Output (New-Object System.Data.DataColumn @($columnName, $type))}
}

$ObjectList = @(
    New-Object psobject -Property @{columnName="FirstName"; type="String"}
    New-Object psobject -Property @{columnName="LastName"; type="String"}
    New-Object psobject -Property @{columnName="Age"; type="Int32"}
)

$ObjectList | Get-Column | Format-Table

, чтобы этот командлетсобирает значения параметров из входного объекта и передает его в свой конструктор пользовательских классов.Кроме того, мне не нужны блоки Begin и End, вероятно, они также избыточны в вашем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...