gpt4 book ai didi

.net - 在 .NET 事件中使用 ref 参数时 PowerShell 崩溃

转载 作者:行者123 更新时间:2023-12-01 23:23:15 25 4
gpt4 key购买 nike

当 .NET 事件带有 ref 时,PowerShell 崩溃我订阅的参数被调用。

我已将问题简化为以下代码。

.NET:

namespace PSEventTest
{
public delegate void BadHandler(ref string str);

public class PSEventTest
{
public event BadHandler BadEvent;

public void InvokeBad()
{
var handler = BadEvent;
if (handler != null)
{
var str = "bad";
handler(ref str);
}
}
}
}

PowerShell:

Add-Type -path $PSScriptRoot"\PSEventTest.dll"

$obj = New-Object PSEventTest.PSEventTest

$bad = Register-ObjectEvent -InputObject $obj -EventName BadEvent -Action {
Write-Host "bad!" # it also crashes if this script-block is empty
}

$obj.InvokeBad(); # crash

当我运行 PowerShell 脚本时,我得到以下信息:

enter image description here

如果我按Debug我从 Visual Studio 得到这个:

enter image description here

copy exception detail to the clipboard给我这个

System.NullReferenceException was unhandled
Message: An unhandled exception of type 'System.NullReferenceException' occurred in Unknown Module.
Additional information: Object reference not set to an instance of an object.

我想我必须将字符串提供给 -Action脚本 block 以某种方式,但我不知道如何。

附注我正在使用 PowerShell 4:

PS C:\Windows\system32> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
4 0 -1 -1

最佳答案

我找到了解决此问题的解决方法:

.NET:

namespace PSEventTest
{
public delegate void BadHandler(ref string str);

public class PSEventTest
{
public event BadHandler BadEvent;

public string InvokeBad()
{
var handler = BadEvent;
if (handler != null)
{
var str = "hi from .NET!";
handler(ref str);
return "from .NET: " + str;
}
return null;
}
}

// as i mention below, this class can be implemented directly in the PS script
public class BadEventSubscriber
{
public void Subscribe(PSEventTest legacyObj, Func<string, string> func)
{
legacyObj.BadEvent += delegate(ref string str)
{
var handler = func;
if (handler != null)
{
var result = handler(str);
str = result;
}
};
}
}
}

PowerShell:

Add-Type -path $PSScriptRoot"\PSEventTest.dll"

$legacyObj = New-Object PSEventTest.PSEventTest
$subscriber = New-Object PSEventTest.BadEventSubscriber

$subscriber.Subscribe($legacyObj, {
param([string]$str)
write-host "from PS: $str"
"hi from PS!"
})

write-host $legacyObj.InvokeBad();

结果:

from PS: hi from .NET!
from .NET: hi from PS!

之前我尝试创建一个 (object sender, EventArgs e)包装 (ref string str) 的处理程序类型处理程序,但这不起作用,因为 PS 事件与 .NET 事件不同步触发。

通过 Func正如上面的代码所示,使用事件处理程序似乎效果更好。

我试图概括 BadEventSubscriber使用Expression<Func<object, handler>>用于从 Subscribe 中传递的对象中选择事件方法,但泛型和 Delegate在一起玩得不好。所以你必须创建一个 BadEventSubsciber -为您想要订阅的每个类和处理程序键入类(PS 不“支持”),但目前对我来说足够好。

这不是真正的解决方案,因为您仍然需要额外的程序集将事件“包装”到 Func 中,但作为一种解决方法,我认为这是可以的。

编辑:

现在我想了想,您可以直接在 PowerShell 中定义订阅者类,就像 @RomanKuzmin 在他的 comment 中所说的那样。我原来的问题。因此,您只需在 PowerShell 中添加以下内容即可代替附加程序集:

Add-Type @"
using System;

public class BadEventSubscriber
{
public void Subscribe(PSEventTest.PSEventTest legacyObj, Func<string, string> func)
{
legacyObj.BadEvent += delegate(ref string str)
{
var handler = func;
if (handler != null)
{
var result = handler(str);
str = result;
}
};
}
}
"@ -ReferencedAssemblies $PSScriptRoot"\PSEventTest.dll"

$subscriber = New-Object BadEventSubscriber

关于.net - 在 .NET 事件中使用 ref 参数时 PowerShell 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30987362/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com