powershell - मैं सशर्त रूप से एड-टाइप-टाइप टाइप परिभाषा के साथ एक वर्ग कैसे जोड़ूं यदि यह पहले से नहीं जोड़ा गया है?




add-type (4)

निम्न PowerShell स्निपेट पर विचार करें:

$csharpString = @"
using System;

public sealed class MyClass
{
    public MyClass() { }
    public override string ToString() {
        return "This is my class. There are many others " +
            "like it, but this one is mine.";
    }
}
"@
Add-Type -TypeDefinition $csharpString;
$myObject = New-Object MyClass
Write-Host $myObject.ToString();

यदि मैं इसे एक ही ऐपडोमेन में एक से अधिक बार चलाता हूं (उदाहरण के लिए powerhell.exe या powershell_ise.exe में स्क्रिप्ट को दो बार चलाएं) मुझे निम्न त्रुटि मिलती है:

Add-Type : Cannot add type. The type name 'MyClass' already exists.
At line:13 char:1
+ Add-Type -TypeDefinition $csharpString;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (MyClass:String) [Add-Type],
 Exception
    + FullyQualifiedErrorId :
 TYPE_ALREADY_EXISTS,Microsoft.PowerShell.Commands.AddTypeCommand

मैं कॉल को Add-Type परिभाषा में कैसे लपेटूं ताकि इसे केवल एक बार बुलाया जा सके?


असल में, इनमें से कोई भी आवश्यक नहीं है। ऐड-टाइप परिणामस्वरूप प्रकार के साथ-साथ आपके द्वारा सबमिट किए गए किसी भी कोड का कैश बनाए रखता है। यदि आप एक ही कोड के साथ दो बार एड-टाइप कहते हैं, तो यह कोड को संकलित करने से परेशान नहीं होगा और आखिरी बार टाइप को वापस कर देगा।

आप पंक्ति में दो बार एक ऐड-टाइप कॉल चलाकर इसे सत्यापित कर सकते हैं।

ऊपर दिए गए उदाहरण में त्रुटि संदेश प्राप्त करने का कारण यह है कि आपने कॉल के बीच कोड को एड-टाइप में बदल दिया है। जबकि उपर्युक्त समाधान इस स्थिति में उस त्रुटि को दूर करता है, इसका मतलब यह भी है कि आप उस प्रकार की पुरानी परिभाषा के साथ काम कर रहे हैं जो संभवतया आपके विचार के तरीके से कार्य नहीं कर रहा है।


इस तरह कोई अपवाद नहीं फेंक दिया जाता है, यह लोड किए गए असेंबली की संख्या पर थोड़ा धीमा आधार है:

[bool]([appdomain]::CurrentDomain.GetAssemblies() | ? { $_.gettypes() -match 'myclass' })

यह तकनीक मेरे लिए अच्छी तरह से काम करती है:

if (-not ([System.Management.Automation.PSTypeName]'MyClass').Type)
{
    Add-Type -TypeDefinition 'public class MyClass { }'
}
  • प्रकार का नाम कोट्स 'माइक्लास', स्क्वायर ब्रैकेट [माइक्लास], या दोनों '[माइक्लास]' (v3 + केवल) में संलग्न किया जा सकता है।
  • प्रकार का नाम लुकअप केस-संवेदी नहीं है।
  • आपको इस प्रकार के पूर्ण नाम का उपयोग करना चाहिए, जब तक कि यह सिस्टम नेमस्पेस का हिस्सा न हो (उदाहरण के लिए [System.DateTime] को 'डेटटाइम' के माध्यम से देखा जा सकता है, लेकिन [System.Reflection.Assembly] को 'असेंबली' के माध्यम से नहीं देखा जा सकता है। )।
  • मैंने केवल Win8.1 में इसका परीक्षण किया है; पावरशेल v2, v3, v4।

आंतरिक रूप से, PSTypeName क्लास LanguagePrimitives.ConvertStringToType () विधि को कॉल करता है जो भारी उठाने को संभालता है। सफल होने पर यह लुकअप स्ट्रिंग को कैश करता है, इसलिए अतिरिक्त लुकअप तेज़ होते हैं।

मैंने पुष्टि नहीं की है कि x0n और जस्टिन डी द्वारा वर्णित किसी भी अपवाद को आंतरिक रूप से फेंक दिया गया है या नहीं।


अपवादों की लागत के बिना ऐसा करने का एक अच्छा तरीका है :

if (-not ("MyClass" -as [type])) {
    add-type @"
        public class MyClass { }
"@
}

अद्यतन: ठीक है, स्पष्ट रूप से शक्तियों आंतरिक रूप से एक अपवाद के साथ संकेत करता है। यह करने की एक बुरी आदत है। दुभाषिया break साथ सिग्नल करने के लिए एसईएच का उपयोग करता है और उदाहरण के लिए कीवर्ड continue