What is the syntax to pass .NET method as a delegate callback to a .NET object in PowerShell.
For example:
C#:
public class Class1
{
public static void MyMethod(Action<object> obj)
{
obj("Hey!");
}
}
public class Class2
{
public static void Callback(object obj)
{
Console.Writeline(obj.ToString());
}
}
PowerShell:
[Class1]::MyMethod([Class2]::Callback)
This doesn't work.
Working code via Adam's and Oisin's chat.
Add-Type -Language CSharpVersion3 -TypeDefinition @"
using System;
public class Class1
{
public static void MyMethod(Action<object> obj)
{
obj("Hey!");
}
}
public class Class2
{
public static void Callback(object obj)
{
Console.WriteLine(obj.ToString());
}
}
"@
$method = [Class2].GetMethod("Callback")
$delegate = [System.Delegate]::CreateDelegate([System.Action[Object]], $null, $method)
[Class1]::MyMethod($delegate)
$code = @'
using System;
public class Class1
{
public static void MyMethod(Action<object> obj)
{
obj("Hey!");
}
}
public class Class2
{
public static void Callback(object obj)
{
Console.WriteLine(obj.ToString());
}
}
'@
Add-Type -TypeDefinition $code -Language CSharpVersion3
[class1]::mymethod([system.action]::CreateDelegate('System.Action[Object]', [class2].getmethod('Callback')))
Via @oising on Twitter:
@adamdriscoll you're spoiled by the c#
compiler's delegate inferencing. You
need to new up that action explicitly,
old school styley.
$method = [Class2].GetMethod("Callback")
$delegate = [System.Delegate]::CreateDelegate([System.Action[Object]], $null, $method
[Class1]::MyMethod($delegate)
The type of [Class2]::Callback
is System.Management.Automation.PSMethod
which apparently cannot be converted by the core to the required delegate.
I am not sure that this is the best way of solving the task (I have not seen any kind of official documentation about this) but the code below works for me in this example case and other similar cases in my practice:
[Class1]::MyMethod({ [Class2]::Callback($args[0]) })
The core is able to convert our script block { [Class2]::Callback($args[0]) }
to the required delegate.
P.S. Though not directly related to the question but here is yet another working example of this technique: using script blocks as match evaluator delegates in regular expressions:
How to sort by file name the same way Windows Explorer does?
I am not an expert at C#, but after reading a couple articles it seems that you are trying to use generic delegates. Your Callback method is not a generic delegate, it isn't even a delegate.
I think this is what you need to do:
C#
public class Class1
{
public static void MyMethod(Action<object> obj)
{
obj("Hey!");
}
}
public class Class2
{
public Action<object> CallBack = obj => Console.WriteLine(obj.ToString());
}
Powershell:
[Class1]::MyMethod([Class2]::Callback)