Подтвердить что ты не робот

Предоставить метод .NET в качестве обратного вызова делегата

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

Например:

С#:

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)

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

4b9b3361

Ответ 1

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

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)

Ответ 2

Через @oising в Twitter:

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

$method = [Class2].GetMethod("Callback") 
$delegate = [System.Delegate]::CreateDelegate([System.Action[Object]], $null, $method
[Class1]::MyMethod($delegate)

Ответ 3

$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

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

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

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

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

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

Ответ 5

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

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

С#

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)