首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Powershell类中正确调用添加了Add-Type的类型的静态方法?

如何在Powershell类中正确调用添加了Add-Type的类型的静态方法?
EN

Stack Overflow用户
提问于 2017-02-10 06:57:50
回答 2查看 839关注 0票数 2

我正在添加此type并将其命名为。它在脚本/函数中工作得很好。只要我试图从powershell类调用它-它就会给出错误"type is not defined“。

我设法使用了一些丑陋的技巧来称呼它。使用-PassThru调用Add-Type,并将结果保存在$global:myType中。然后我使用$global:myType.GetMethod('GetSymbolicLinkTarget').invoke($null,$dir)进行间接调用。

有没有更好的解决方案?

PS:运行空间在每次运行前重置(在ISE中为Ctrl-T,在PowerGUI和Powershell Studio中为automatic )。

PS2:工作示例(简体)如下。

代码语言:javascript
复制
#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为here提供了另外两个变通方法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-11 08:24:29

另外两种解决方法:

代码语言:javascript
复制
#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是最短和最干净的。

使用类型加速器也是可能的。

票数 1
EN

Stack Overflow用户

发布于 2017-02-11 08:24:27

问题是类是在编译时解析的,直到运行时才会添加对您添加的类型的引用。因此,无法解析引用。

我看到的最好的解决方案是强制它们的编译顺序。

代码语言:javascript
复制
# 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()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42148492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档