我正在添加此类型并调用它。它在脚本/函数中工作正常。一旦我尝试从 powershell 类调用它 - 它就会给出错误"类型未定义"。
我已经设法使用一些丑陋的黑客来称呼它。 Add-Type
随-PassThru
调用,结果保存在 $global:myType
中。然后我正在使用$global:myType.GetMethod('GetSymbolicLinkTarget').invoke($null,$dir)
进行间接调用。
周围有更好的解决方案吗?
PS:运行空间在每次运行前被重置(ISE中的Ctrl-T,PowerGUI和Powershell Studio中的自动(。
PS2:工作示例(简化(如下。
#works - returns 2
$Source = ' public class BasicTest { public static int Test(int a) { return (a + 1); } } '
Add-Type -TypeDefinition $Source
[BasicTest]::Test(1)
#gives error: Unable to find type [BasicTest]
$Source = ' public class BasicTest { public static int Test(int a) { return (a + 1); } } '
Add-Type -TypeDefinition $Source
class foo { Static [int]bar() { return [BasicTest]::Test(1) } }
[foo]::bar()
#workaround 1 - indirect call with GetMethod(...).Invoke(...)
# returns 4
$Source = ' public class BasicTest1 { public static int Test(int a) { return (a + 1); } } '
$global:BasicTestType1 = (Add-Type -TypeDefinition $Source -PassThru)
class foo {
static $BasicTestType2 = (Add-Type -TypeDefinition ' public class BasicTest2 { public static int Test(int a) { return (a + 1); } } ' -PassThru)
Static [int]bar() {
$ret = $global:BasicTestType1.GetMethod('Test').Invoke($null, [int]1)
$ret += [foo]::BasicTestType2.GetMethod('Test').Invoke($null, [int]1)
return $ret
}
}
[foo]::bar()
#workaround 2 - invoke-expression; has problems passing parameters
# returns 2
$Source = ' public class BasicTest { public static int Test(int a) { return (a + 1); } } '
Add-Type -TypeDefinition $Source
class foo { Static [int]bar() { return invoke-expression '[BasicTest]::Test(1)' } }
[foo]::bar()
PS3:PetSerAl提供了另外两种解决方法。
问题是该类是在编译时解析的,并且直到运行时才会添加对添加的类型的引用。 因此,无法解析引用。
我看到的最佳解决方案是强制按编译顺序编译它们。
# Add the type
$Source = ' public class BasicTest { public static int Test(int a) { return (a + 1); } } '
Add-Type -TypeDefinition $Source
$scriptBlockText = @"
class foo {
Static foo() {
}
Static [int]bar() { return [BasicTest]::Test(1) }
}
"@
# Create a script block from the text
# the class will be compiled at this point
# but is not in scope yet
$scriptBlock = [scriptblock]::Create($scriptBlockText)
# dot source the class
# this brings the class into scope
.([scriptblock]::Create($scriptBlock))
# it would be better if the class was in a separate file
# but I'm using a string to simplify the sample.
# for a file the syntax would be `. .myClass.ps1`
# this would replace both creating the script block and
# the dot sourcing statement
# Now you can use the class and the type you addded earlier
[foo]::bar()
另外两种解决方法:
#workaround 3 - type variable
# returns 4
$Source = ' public class BasicTest1 { public static int Test(int a) { return (a + 1); } } '
$global:BasicTestType1 = (Add-Type -TypeDefinition $Source -PassThru)
class foo {
static $BasicTestType2 = (Add-Type -TypeDefinition ' public class BasicTest2 { public static int Test(int a) { return (a + 1); } } ' -PassThru)
Static [int]bar() {
$ret = ($global:BasicTestType1)::Test(1)
$ret += ([foo]::BasicTestType2)::Test(1)
return $ret
}
}
[foo]::bar()
#workaround 4 - most elegant so far
# returns 2
class foo {
static foo() {
$Source = ' namespace foo { public class BasicTest1 { public static int Test(int a) { return (a + 1); } } } '
Add-Type -TypeDefinition $Source
}
Static [int]bar() {
$ret = ([type]'foo.BasicTest1')::Test(1)
return $ret
}
}
[foo]::bar()
解决方法 4 最短且最干净。
也可以使用类型加速器。