Предоставить метод .NET в качестве обратного вызова делегата. - PullRequest
16 голосов
/ 03 апреля 2011

Каков синтаксис для передачи метода .NET в качестве обратного вызова делегата к объекту .NET в PowerShell.

Например:

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)

Это не работает.

Ответы [ 5 ]

12 голосов
/ 03 апреля 2011

Рабочий код через чат Адама и Ойсина.

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)
4 голосов
/ 03 апреля 2011
$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')))
4 голосов
/ 03 апреля 2011

Через @ oising в Твиттере :

@ adamdriscoll вы испорчены выводом делегата компилятора c #Вам нужно явно обновить это действие, в стиле старой школы.

$method = [Class2].GetMethod("Callback") 
$delegate = [System.Delegate]::CreateDelegate([System.Action[Object]], $null, $method
[Class1]::MyMethod($delegate)
3 голосов
/ 03 апреля 2011

Тип [Class2]::Callback равен System.Management.Automation.PSMethod, который, очевидно, не может быть преобразован ядром в требуемый делегат.

Я не уверен, что это лучший способ решения задачи (я не видел никакой официальной документации по этому поводу), но приведенный ниже код работает для меня в этом примере и других подобных случаях в моей практике:

[Class1]::MyMethod({ [Class2]::Callback($args[0]) })

Ядро может преобразовать наш блок скриптов { [Class2]::Callback($args[0]) } в требуемый делегат.

P.S. Хотя это и не связано напрямую с вопросом, но вот еще один рабочий пример этого метода: использование блоков сценариев в качестве делегатов для оценки соответствия в регулярных выражениях: Как отсортировать по имени файла так же, как это делает проводник Windows?

1 голос
/ 03 апреля 2011

Я не эксперт в C #, но после прочтения пары статей кажется, что вы пытаетесь использовать универсальные делегаты. Ваш метод обратного вызова не является универсальным делегатом, он даже не делегат.

Я думаю, это то, что вам нужно сделать:

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)
...