Передача данных в PSCmdlet из его атрибута ArgumentTransformationAttribute - PullRequest
0 голосов
/ 18 февраля 2012

Как правило, я пытаюсь создать PSCmdlet, который принимает параметр типа, который реализует IDisposeable и требует удаления во избежание утечки ресурсов.Я также хотел бы принять string для этого параметра и создать экземпляр этого типа, однако, если я сам создаю этот объект, мне нужно избавиться от него перед возвратом из ProcessRecord.

I 'используя ArgumentTransformationAttribute с моим параметром для создания моего IDisposeable объекта из строки, но я не могу найти способ передать данные из этого класса в мой PSCmdlet о том, создал ли я объект или нет.Например:

[Cmdlet("Get", "MyDisposeableName")]
public class GetMyDisposeableNameCommand : PSCmdlet
{
    [Parameter(Mandatory = true, Position = 0), MyDisposeableTransformation]
    public MyDisposeable MyDisposeable
    {
        get;
        set;
    }

    protected override void ProcessRecord()
    {
        try
        {
            WriteObject(MyDisposeable.Name);
        }
        finally
        {
            /* Should only dispose MyDisposeable if we created it... */
            MyDisposeable.Dispose();
        }
    }
}

class MyDisposeableTransformationAttribute : ArgumentTransformationAttribute
{
    public override Object Transform(EngineIntrinsics engineIntrinsics, Object input)
    {
        if (input is PSObject && ((PSObject)input).BaseObject is MyDisposeable)
        {
            /* We were passed a MyDisposeable, we should not dispose it */
            return ((PSObject)input).BaseObject;
        }

        /* We created a MyDisposeable, we *should* dispose it */
        return new MyDisposeable(input.ToString());
    }
}

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

Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 27 февраля 2012

В конце я просто использую параметры, которые принимают тип, который переносит MyDisposeable.Моя первоначальная задача заключалась в том, чтобы использование внутреннего типа для параметра могло повлиять на доступность функций.(Возможно, это негативно повлияет на документацию, но в командлете документация полностью контролируется XML-файлом.)

После некоторого тестирования не возникает проблем с использованием внутреннего класса для параметра ипозволяя преобразованию принимать открытые типы.Поэтому я просто создаю класс-оболочку:

public class MyDisposeableWrapper
{
    public MyDisposeable MyDisposeable
    {
        get;
        set;
    }

    public bool NeedsDisposed
    {
        get;
        set;
    }

    public MyDisposeableWrapper(MyDisposeable myDisposeable, bool needsDisposed)
    {
        MyDisposeable = myDisposeable;
        NeedsDisposed = needsDisposed;
    }
}

, и вместо этого принимаю параметр.В атрибуте преобразования просто установите NeedsDisposed в зависимости от того, принял ли параметр MyDisposeable или сконструировал его.например:

if(input is MyDisposeable)
{
    return new MyDisposeableWrapper((MyDisposeable) input, false);
}
else
{
    /* construct MyDisposeable from the input */
    return new MyDisposeableWrapper(myDisposeable, true);
}
0 голосов
/ 18 февраля 2012

Вместо того, чтобы создавать подклассы, можете ли вы добавить свойство в свой класс MyDisposable?

public class MyDisposable
{
    ...   
    public bool IsAttributeCreated { get; set; }
}

Затем в вашем коде атрибута

/* We created a MyDisposeable, we *should* dispose it */
return new MyDisposeable(input.ToString()){IsAttributeCreated=true};

Наконец, в вашем блоке finally

finally
{
    /* Should only dispose MyDisposeable if we created it... */
    if (MyDisposable.IsAttributeCreated)
        MyDisposeable.Dispose();
}
...