将数据从 ArgumentTransformationAttribute 传递到 PSCmdlet
一般来说,我尝试创建一个 PSCmdlet
,它采用实现 IDisposeable
的类型的参数,并需要进行处置以避免泄漏资源。我还想接受该参数的字符串并创建该类型的实例,但是如果我自己创建该对象,那么我需要在从 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
进行子类化,只是为了标记它需要显式处置,但这看起来相当老套,虽然它在这种情况下有效,但如果我想要处理一个密封类。
有更好的方法吗?
Generally, I'm trying to create a PSCmdlet
that takes a parameter of a type that implements IDisposeable
and requires disposal in order to avoid leaking resources. I would also like to accept a string
for that parameter and create an instance of that type, however if I create that object myself, then I need to dispose it before returning from ProcessRecord
.
I'm using an ArgumentTransformationAttribute
with my parameter in order to construct my IDisposeable
object from a string, but I cannot find any way to pass data from that class to my PSCmdlet
about whether I created the object or not. For example:
[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());
}
}
My best guess here is to subclass my MyDisposeableClass
just to tag that it needs explicit disposal, but that seems fairly hacky, and while it works in this case, it obviously wouldn't work if I wanted to deal with a sealed class.
Is there a better way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否可以向 MyDisposable 类添加一个属性,而不是子类化?
然后在你的属性代码中
最后在你的finally块中
Rather than subclassing, can you add a property to your MyDisposable class?
Then in your attribute code
Finally in your finally block
最后,我只是使用接受包装
MyDisposeable
类型的参数。我最初担心这样做是使用内部类型作为参数会影响函数的可访问性。 (也许这会对文档产生负面影响,但在 cmdlet 中,文档完全由 XML 文件控制。)经过一些测试,使用内部类作为参数并让转换接受公共类型似乎没有任何问题。所以我只是创建一个包装类:
并让参数采用它。在转换属性中,只需根据参数是采用
MyDisposeable
还是构造参数来设置NeedsDispose
即可。例如:In the end, I simply use parameters that accept a type that wraps
MyDisposeable
. My initial concern with doing this was that using an internal type for a parameter would impact the functions accessibility. (Perhaps it would negatively impact documentation, but in a cmdlet the documentation is wholly controlled by an XML file.)After some testing, there do not appear to be any problems using an internal class for a parameter and just letting the transformation accept public types. So I simply create a wrapper class:
And have the parameter take that instead. In the transformation attribute, simply set
NeedsDisposed
based on whether the parameter took aMyDisposeable
or constructed one. eg: