تمرير البيانات إلى PSCmdlet من ArgumentTransformationAttribute الخاص بها
-
27-10-2019 - |
سؤال
بشكل عام، أحاول إنشاء ملف PSCmdlet
يأخذ معلمة من النوع الذي يتم تنفيذه IDisposeable
ويتطلب التخلص منها لتجنب تسرب الموارد.أود أيضًا أن أقبل أ string
لهذه المعلمة وإنشاء مثيل من هذا النوع، ولكن إذا قمت بإنشاء هذا الكائن بنفسي، فسأحتاج إلى التخلص منه قبل العودة من ProcessRecord
.
أنا أستخدم ArgumentTransformationAttribute
مع المعلمة الخاصة بي من أجل بناء ملفي IDisposeable
كائن من سلسلة، ولكن لا يمكنني العثور على أي طريقة لتمرير البيانات من تلك الفئة إلى فئة My 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
في النهاية، أستخدم ببساطة المعلمات التي تقبل النوع الذي يلتف 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
بناءً على ما إذا كانت المعلمة قد أخذت a MyDisposeable
أو شيدت واحدة.على سبيل المثال:
if(input is MyDisposeable)
{
return new MyDisposeableWrapper((MyDisposeable) input, false);
}
else
{
/* construct MyDisposeable from the input */
return new MyDisposeableWrapper(myDisposeable, true);
}
نصائح أخرى
بدلاً من التصنيف الفرعي، هل يمكنك إضافة خاصية إلى فئة 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
{
/* Should only dispose MyDisposeable if we created it... */
if (MyDisposable.IsAttributeCreated)
MyDisposeable.Dispose();
}