PowerShell crashes when using ref parameter in .NET event PowerShell crashes when using ref parameter in .NET event powershell powershell

PowerShell crashes when using ref parameter in .NET event


I found a work-around for this problem:

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

The result:

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

Previously I tried to create a (object sender, EventArgs e) type of handler to wrap the (ref string str) handler, but that did not work, because the PS event was fired out of sync with the .NET event.

Passing a Func in stead of using an event handler seems to work a lot better, as demonstrated in the code above.

I tried to generalize the BadEventSubscriber to use a Expression<Func<object, handler>> for selecting the event off of the passed object in the Subscribe method, but generics and Delegate don't play well together. So you would have to create a BadEventSubsciber-type class for every class and handler you would want to subscribe to (that PS does not "support"), but is it good enough for me at the moment.

Its no real solution, as you would still need the additional assembly to "wrap" the event into a Func, but as a work-around i think it is okay.

EDIT:

Now that i think about it, you can just define the subscriber class directly in PowerShell like @RomanKuzmin said in his comment to my original question. So instead of the additional assembly you just have the following in your 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