憨厚的企鹅 · pytorch OSError: ...· 3 月前 · |
帅气的闹钟 · Java获取的一天、本星期、这个月、本季度、 ...· 3 月前 · |
健壮的大熊猫 · 垂直领域大模型微调最全指南_垂域大模型-CS ...· 5 月前 · |
忐忑的钢笔 · jchsinker-java去重写click ...· 1 年前 · |
深沉的板栗 · window.location.hash的简 ...· 1 年前 · |
如何在Powershell中调用自定义类的泛型静态方法?
给定以下类:
public class Sample
public static string MyMethod<T>( string anArgument )
return string.Format( "Generic type is {0} with argument {1}", typeof(T), anArgument );
}
它被编译成一个程序集'Classes.dll‘并加载到PowerShell中,如下所示:
Add-Type -Path "Classes.dll"
调用MyMethod方法的最简单方法是什么?
你可以调用泛型方法,参考post Invoking Generic Methods on Non-Generic Classes in PowerShell 。
这并不简单,你需要使用
MakeGenericMethod
函数。如果方法没有重写,那就很简单了;如果重写了,那就更难了。
以防万一,从那里复制粘贴代码:
## Invoke-GenericMethod.ps1
## Invoke a generic method on a non-generic type:
## Usage:
## ## Load the DLL that contains our class
## [Reflection.Assembly]::LoadFile("c:\temp\GenericClass.dll")
## ## Invoke a generic method on a non-generic instance
## $nonGenericClass = New-Object NonGenericClass
## Invoke-GenericMethod $nonGenericClass GenericMethod String "How are you?"
## ## Including one with multiple arguments
## Invoke-GenericMethod $nonGenericClass GenericMethod String ("How are you?",5)
## ## Ivoke a generic static method on a type
## Invoke-GenericMethod ([NonGenericClass]) GenericStaticMethod String "How are you?"
param(
$instance = $(throw "Please provide an instance on which to invoke the generic method"),
[string] $methodName = $(throw "Please provide a method name to invoke"),
[string[]] $typeParameters = $(throw "Please specify the type parameters"),
[object[]] $methodParameters = $(throw "Please specify the method parameters")
## Determine if the types in $set1 match the types in $set2, replacing generic
## parameters in $set1 with the types in $genericTypes
function ParameterTypesMatch([type[]] $set1, [type[]] $set2, [type[]] $genericTypes)
$typeReplacementIndex = 0
$currentTypeIndex = 0
## Exit if the set lengths are different
if($set1.Count -ne $set2.Count)
return $false
## Go through each of the types in the first set
foreach($type in $set1)
## If it is a generic parameter, then replace it with a type from
## the $genericTypes list
if($type.IsGenericParameter)
$type = $genericTypes[$typeReplacementIndex]
$typeReplacementIndex++
## Check that the current type (i.e.: the original type, or replacement
## generic type) matches the type from $set2
if($type -ne $set2[$currentTypeIndex])
return $false
$currentTypeIndex++
return $true
## Convert the type parameters into actual types
[type[]] $typedParameters = $typeParameters
## Determine the type that we will call the generic method on. Initially, assume
## that it is actually a type itself.
$type = $instance
## If it is not, then it is a real object, and we can call its GetType() method
if($instance -isnot "Type")
$type = $instance.GetType()
## Search for the method that:
## - has the same name
## - is public
## - is a generic method
## - has the same parameter types
foreach($method in $type.GetMethods())
# Write-Host $method.Name
if(($method.Name -eq $methodName) -and
($method.IsPublic) -and
($method.IsGenericMethod))
$parameterTypes = @($method.GetParameters() | % { $_.ParameterType })
$methodParameterTypes = @($methodParameters | % { $_.GetType() })
if(ParameterTypesMatch $parameterTypes $methodParameterTypes $typedParameters)
## Create a closed representation of it
$newMethod = $method.MakeGenericMethod($typedParameters)
## Invoke the method
$newMethod.Invoke($instance, $methodParameters)
return
## Return an error if we couldn't find that method
throw "Could not find method $methodName"
正如@Athari所说,调用MyMethod最简单的方法就是使用MakeGenericMethod。由于他实际上并没有展示如何做到这一点,下面是一个经过验证的工作代码示例:
$obj = New-Object Sample
$obj.GetType().GetMethod("MyMethod").MakeGenericMethod([String]).Invoke($obj, "Test Message")
$obj.GetType().GetMethod("MyMethod").MakeGenericMethod([Double]).Invoke($obj, "Test Message")
带输出
Generic type is System.String with argument Test Message
Generic type is System.Double with argument Test Message
好消息是PowerShell v3更擅长绑定到泛型方法(并将其具体化?)而且您通常不需要做任何特殊的事情,而是像调用普通方法一样调用它。我不能指定现在适用的所有标准,但根据我的经验,即使在PowerShell v4中,使用泛型参数的某些情况仍然需要变通(可能是因为存在或重载或类似的原因)。
类似地,我有时也会在向方法传递泛型参数时遇到问题……例如,传递
Func<T1, T2, TResult>
参数。
对我来说,一个比MakeGenericMethod或其他方法简单得多的变通办法是直接在我的脚本中放置一个快速的C#包装器类,并让C#对所有通用映射进行排序……
以下是包装
Enumerable.Zip
方法的此方法的示例。在本例中,我的c#类根本不是泛型的,但严格地说,这并不是必需的。
Add-Type @'
using System.Linq;
public class Zipper
public static object[] Zip(object[] first, object[] second)
return first.Zip(second, (f,s) => new { f , s}).ToArray();
$a = 1..4;
[string[]]$b = "a","b","c","d";
健壮的大熊猫 · 垂直领域大模型微调最全指南_垂域大模型-CSDN博客 5 月前 |