programing

Add-Type-TypeDefinition이 추가되지 않은 클래스를 조건부로 추가하려면 어떻게 해야 합니까?

oldcodes 2023. 9. 21. 21:14
반응형

Add-Type-TypeDefinition이 추가되지 않은 클래스를 조건부로 추가하려면 어떻게 해야 합니까?

다음과 같은 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();

동일한 AppDomain에서 두 번 이상 실행하면(예: powershell.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-TypeDefinition으로 랩핑하려면 어떻게 해야 합니까?

이 기술은 제게 적합합니다.

if (-not ([System.Management.Automation.PSTypeName]'MyClass').Type)
{
    Add-Type -TypeDefinition 'public class MyClass { }'
}
  • 형식 이름은 따옴표 'MyClass', 대괄호 [MyClass] 또는 둘 다 '[MyClass]'(v3+만)로 묶을 수 있습니다.
  • 형식 이름 조회는 대소문자를 구분하지 않습니다.
  • 시스템 네임스페이스(예: [System])의 일부가 아닌 경우 유형의 전체 이름을 사용해야 합니다.DateTime]은(는) 'DateTime'을 통해 조회할 수 있지만, [System].반사.Assembly]는 'Assembly')를 통해 조회할 수 없습니다.
  • Win8.1, PowerShell v2, v3, v4에서만 테스트했습니다.

PTypeName 클래스는 내부적으로 LanguagePrimitives를 호출합니다.무거운 리프팅을 처리하는 ConvertStringToType() 메서드입니다.성공하면 조회 문자열을 캐시하기 때문에 추가 조회가 더 빠릅니다.

x0n과 Justin D가 언급한 것처럼 내부적으로 예외가 던져지는지 확인하지 못했습니다.

사실, 이것은 필요하지 않습니다.Add-Type은 사용자가 제출한 코드의 캐시를 결과 유형과 함께 유지 관리합니다.동일한 코드로 Add-Type을 두 번 호출하면 코드를 컴파일하는 데 지장이 없고 지난번에 호출한 코드만 반환됩니다.

Add-Type 호출을 두 번 연속 실행하면 이를 확인할 수 있습니다.

위 예제에서 오류 메시지가 나온 이유는 호출 간의 코드를 Add-Type으로 변경했기 때문입니다.위의 솔루션은 이러한 상황에서 이러한 오류를 제거할 수 있지만, 이는 여러분이 생각하는 대로 행동하지 않을 수도 있는 유형에 대한 이전 정의를 사용하고 있다는 것을 의미합니다.

더 좋은 방법이 있습니다. 예외의 비용을 들이지 않고 :

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

업데이트: 음, 어쨌든 예외를 제외하고 내부적으로 파워셸 신호를 보내는 것으로 보입니다.이것을 하는 나쁜 습관이 있습니다.인터프리터는 SEH를 사용하여 신호를 전송합니다.break그리고.continue예를 들어 키워드를 입력합니다.

가장 간단한 방법은 시도/잡기 블록입니다.이 작업에는 두 가지 옵션이 있습니다.

  • try { [MyClass] | Out-Null } catch { Add-Type -TypeDefinition $csharpString; }
  • try { Add-Type -TypeDefinition $csharpString; } catch {}

이렇게 하면 예외가 발생하지 않으며 로드된 어셈블리의 수에 따라 약간 느릴 뿐입니다.

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

언급URL : https://stackoverflow.com/questions/16552801/how-do-i-conditionally-add-a-class-with-add-type-typedefinition-if-it-isnt-add

반응형