0

通常,我正在尝试创建一个PSCmdlet采用实现IDisposeable并需要处置的类型的参数以避免泄漏资源的参数。我还想接受string该参数的 a 并创建该类型的实例,但是如果我自己创建该对象,那么我需要在从ProcessRecord.

我正在使用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只是为了标记它需要显式处理,但这似乎相当hacky,虽然它在这种情况下有效,但如果我想处理一个密封的类,它显然是行不通的。

有一个更好的方法吗?

4

2 回答 2

0

您可以向 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();
}
于 2012-02-18T18:09:52.967 回答
0

最后,我只是使用接受包装类型的参数MyDisposeable。我最初担心的是,对参数使用内部类型会影响函数的可访问性。(也许它会对文档产生负面影响,但在 cmdlet 中,文档完全由 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);
}
于 2012-02-27T15:40:54.987 回答