【问题标题】:Calling static generic LINQ extension method in PowerShell在 PowerShell 中调用静态通用 LINQ 扩展方法
【发布时间】:2017-05-10 03:19:12
【问题描述】:

可以用这个简单的符号在 PowerShell 中调用许多 LINQ 方法:

[int[]] $numbers = 1..10000
[Linq.Enumerable]::Sum($numbers)

在调用中包含一个 lambda 甚至是一件相对简单的事情:

[Func[int,int]] $delegate = { $n = $args[0]; if ($n % 3) { $n } else { -$n } }
[Linq.Enumerable]::Sum($numbers, $delegate)

不过,我想知道的是如何从 PowerShell 调用 generic LINQ 方法:这可能吗? 我发现this SO question 似乎表明可以,但我还没有确定如何将该信息应用于 LINQ。 (另外,这是旧信息,PS 版本 5 很可能有更简洁的方法。)

那么如何在 PowerShell 中正确调用 [Linq.Enumerable]::Cast<T>(...)[Linq.Enumerable]::OfType<T>(...)

2017.05.10 更新

好的,所以基于@Mathias 的评论,让我们坚持使用MakeGenericMethod。在 C# 中,这个咒语有效:

var ofTypeForString = typeof(System.Linq.Enumerable).GetMethod("OfType").MakeGenericMethod(typeof(string));
var stuff = new object[] { 1.2, "abc", "def" };
var results = ofTypeForString.Invoke(null, new[] { stuff });

我仍然缺少的部分是如何将typeof(System.Linq.Enumerable) 转换为 PowerShell。我认为至少其中一个应该可以工作,但它们都返回 null:

[System.Type]::GetType("System.Linq.Enumerable")
[System.Type]::GetType("Linq.Enumerable")
[System.Type]::GetType("Enumerable")

我确定我错过了一些简单的东西;建议?

【问题讨论】:

  • 不,PowerShell(从版本 5 开始)仍然没有通用扩展方法的语法。您找到的示例仍然是要走的路
  • 我仍然缺少的部分是如何将typeof(System.Linq.Enumerable) 转换为 PowerShell。 [Linq.Enumerable]
  • Type.GetType(string) takes "[t] 要获取的类型的程序集限定名称。参见AssemblyQualifiedName。"因此,您需要将其称为[System.Type]::GetType("System.Linq.Enumerable,System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").GetMethod("OfType")。不过,您也应该能够做到[System.Linq.Enumerable].GetMethod("OfType")

标签: linq powershell generics extension-methods


【解决方案1】:

是的,PetSerAl 和 ejohnson 的 cmets 都是正确的,当然;我只是因为某种原因出现了精神障碍。因此,对于那些可能感兴趣的人来说,这里是完整的解决方案:

$stringType = "".GetType() # set to your target type
$ofTypeForString =
        [Linq.Enumerable].GetMethod("OfType").MakeGenericMethod($stringType)
$stuff = @("12345", 12, "def")
# The last comma below wraps the array arg $stuff within another array
$ofTypeForString.Invoke($null, (,$stuff)) 

【讨论】:

  • 如果方法重载,你知道怎么做吗?我试图弄清楚如何为 Linq.Enumerable 中的 except() 方法执行此操作,但我收到一条错误消息:使用“1”参数调用“GetMethod”的异常:“找到模糊匹配。 "因为它不知道我想要哪一个(带有 1 个或两个参数的那个)。
  • 对于Except 方法,您不需要将其视为通用调用;你可以简单地使用,例如[int[]] $numbersA = @(0, 2, 4, 5, 8); [int[]] $numbersB = @(5, 2, 7, 1); [Linq.Enumerable]::Except($numbersA, $numbersB);。我向您推荐我刚刚发表的综合文章,其中说明了这一点以及更多内容:High Performance PowerShell with LINQ
猜你喜欢
  • 2011-05-13
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-23
  • 2015-03-28
相关资源
最近更新 更多