2

One can call many LINQ methods in PowerShell with this simple notation:

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

It is even a relatively simple matter to include a lambda in a call:

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

What I am wondering, though, is how to call a generic LINQ method from PowerShell: is it even possible? I found this SO question that seems to indicate one can, but I have not determined how to apply that info to LINQ. (Plus, the fact that that is old information, it is quite possible that with PS version 5 there is a cleaner way to do it.)

So how could one call [Linq.Enumerable]::Cast<T>(...) or [Linq.Enumerable]::OfType<T>(...) properly in PowerShell?

2017.05.10 Update

OK, so based on @Mathias comment, let's stick with MakeGenericMethod. In C#, this incantation works:

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 }); 

The piece I am still missing is how to translate typeof(System.Linq.Enumerable) to PowerShell. I thought that at least one of these should work but they all return null:

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

I am sure I am missing something simple; suggestions?

3
  • No, PowerShell (as of version 5) still has no syntax for generic extension methods. The example you found is still the way to go Commented May 10, 2017 at 8:59
  • The piece I am still missing is how to translate typeof(System.Linq.Enumerable) to PowerShell. [Linq.Enumerable] Commented May 11, 2017 at 4:48
  • Type.GetType(string) takes "[t]he assembly-qualified name of the type to get. See AssemblyQualifiedName." As such, you need to call it like [System.Type]::GetType("System.Linq.Enumerable,System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").GetMethod("OfType"). You should also just be able to do [System.Linq.Enumerable].GetMethod("OfType"), though. Commented May 15, 2017 at 21:35

1 Answer 1

3

Yes, both PetSerAl and ejohnson's comments are correct, of course; I just had a mental block for some reason. So here is the complete solution for those who may be interested:

$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)) 
Sign up to request clarification or add additional context in comments.

2 Comments

Do you know how to do this if the method is overloaded? I'm trying to figure out how to do it for the except() method in Linq.Enumerable but I'm getting an error which says: Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found." since it doesn't know which one I want (The one with 1 or two parameters).
For the Except method you do not need to treat it as a generic call; you can simply use, e.g. [int[]] $numbersA = @(0, 2, 4, 5, 8); [int[]] $numbersB = @(5, 2, 7, 1); [Linq.Enumerable]::Except($numbersA, $numbersB);. I refer you to my just-published comprehensive article that illustrates this and lots more: High Performance PowerShell with LINQ

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.