Attaching Custom MetaData to Functions
February 1st, 2011 by KarlOne nice thing about object in dotnet, including ETS PowerShell objects is the ability to really store MetaData with a variety of techniques, then later you can walk up to an object programatically, and ask it about itself.
However there really isn’t a way to do this out of the box when it comes to Functions (other than finding out the intrinsic attributes of functions.
One common way is with DotnetAttributes. Most know that there were Certian Dotnet Attributes added to PowerShell V2, such as [Parameter()] and [CmdletBinding()]
A little known secret is that you can actually use ANY dotnet attribute. And as they aren’t really attached to objects like Attributes are on a real dotnet objects so they are totally benign, you just have to work out where to attach it and which attributes to use.
You can attach them to the Function’s ScriptBlock, or its parameters. I find for general MetaData storage the scriptblock is the best place to put it.
Next what attribute. Well you could make your own in C# and use add-type, or you could just pilfer some that are part of the dotnet framework that have agreeable names. Remember they are benign in this context so it really doesn’t matter.
function demo-attributes
{
[System.Configuration.SettingsDescription({
@{something = 1;
this = 'that';
array = (1,2,3);
sub = @{ sub1 = 1 ; sub2 =2 }
}})]
[CmdletBinding(DefaultParameterSetName="noname")]
param (
[Parameter(Position=1,mandatory = $true)]
[string]$something
)
1..10
}
So you’ll notice i choose a simple advanced function that already has some dotnetattributes on it, You don’t have to, it could be a simple function, or even an unnamed scriptblock.
in this case used the dotnet Attribute System.Configuration.SettingsDescription and passed in a scriptblock that returned a hashtable containing a complex object.
So this is all good, but the purpose of MetaData is to be able to read it later. My strategy involves
- Find the attribute on the function’s scriptblock
- Grab the string from it
- Put it in a Powershell Data Language DATA section to ensure its content can only be benign
- Evaluate it to get the complex objects back
$settingstext = ((dir function:\demo-attributes).scriptblock.attributes |Where-Object { $_.typeid -like '*settingsdescription*' }).description
$settingsscriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("DATA {" + $settingstext + "}")
&$settingsscriptblock
Posted in Powershell | No Comments »
