Of Powershell And Compiled Events

After writing my last post I realized that I didn’t have a script that would simplify the process of generating event handlers down to a single line task.

I quickly wrote a script that wraps C# method code into a delegate. The script allows delegates of any signature to be created. The result has four parameters, three of witch have default values, and only 17 lines of actual code. This script should be fairly easy to use.

The default values are set to use the EventHandler delegate. I chose this type of delegate because Powershell script blocks can be cast to EventHandler. I wanted to be able to easily generate a compiled delegate and be able to combine it with a script block.

Get-CDelegate.ps1

Here is an example of its use.

PS> $handler = Get-CDelegate 'Console.WriteLine("Hello world!");'
PS> $handler.Invoke($null,$null)
Hello world!

Simple! Right? Think of the compiled delegate as if it were a script block that runs really fast.

You can also make delegates of different types.

PS> $callback = Get-CDelegate 'Console.WriteLine("Hello world!");' -DelegateType AsyncCallback -Signature void, IAsyncResult

Here’s the cool part. Combine a script block with an event handler to make a new event hander.

PS> $eh1 = get-cdelegate 'Console.WriteLine("Compiled EventHandler!");'
PS> $eh2 = [eventhandler]{write-host 'ScriptBlock!'} PS> $eh3 = [delegate]::combine($eh1, $eh2) PS> $eh3.invoke($null,$null) Compiled EventHandler! ScriptBlock!

There is also a using parameter. Add any namespaces that you want to use there. The default is ‘System’.

Now, take it, have it, play with it, enjoy it, and remember, the key making this useful is to keep in mind that the result of this script is a reusable function that can do something that is hard much faster than an ordinary script block. Now go find an interesting use for this and post about it!

Update

I expanded the script so that the delegate can receive an object from the script that made it and also be able to remember past invocations. Script blocks store all their context information as variables, but that’s not so easy in this case. Here there is no guarantee that there is even a Runspace associated with the thread that invokes the delegate. Now you can provide an initialization object, optional initialization code, and define the types for any values that should remain present between invocations.

PS> $eh = get-cdelegate 'context0++; Console.WriteLine(context0);' -contexttypes int -initobject 50 -initcode 'context0 = (int)init.BaseObject;'
PS> $eh.invoke($null,$null)
51
PS> $eh.invoke($null,$null)
52
PS> $eh.invoke($null,$null)
53
PS> $eh.invoke($null,$null)
54

Advertisements

~ by lunaticexperimentalist on May 27, 2008.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: