How to dynamically define a class in C# PowerShell Cmdlet
I have some data I'm getting from a datasource which is a bunch of name/value pairs that I store in a Dictionary<string, object>.
I want to define a class on the fly, with properties that map to the key/value pairs from the dictionary and methods based on the type of data it represents. This would allow the user of the cmdlet to access the values as properties of an object and also invoke methods on it.
I see an example of this with Get-WmiObject. It returns instances of ManagementObject (which is basically a generic property bag) but the user is able to access the properties and invoke methods on it directly (i.e. without having to call the GetPropertyValue/InvokeMethod methods on ManagementObject).
PS C:\temp> $comp = Get-WmiObject Win32_ComputerSystem
PS C:\temp> $comp | Get-Member
TypeName: System.Management.ManagementObject#root\cimv2\Win32_ComputerSystem
Name MemberType Definition
---- ---------- ----------
JoinDomainOrWorkgroup Method System.Management.ManagementBaseObject JoinDomainO
Rename Method System.Management.ManagementBaseObject Rename(Syst
SetPowerState Method System.Management.ManagementBaseObject SetPowerSta
UnjoinDomainOrWorkgroup Method System.Management.ManagementBaseObject UnjoinDomai
AdminPasswordStatus Property System.UInt16 AdminPasswordStatus {get;set;}
AutomaticManagedPagefile Property System.Boolean AutomaticManagedPagefile {get;set;}
AutomaticResetBootOption Property System.Boolean AutomaticResetBootOption {get;set;}
... etc ...
How do I do this with my own objects?
UPDATE
Accepting Keith's answer which is a general .NET framework approach for generating code dynamically. This should work for my scenario although I think it might be overkill.
I was hopin开发者_如何学Pythong someone would provide a clear example of doing this using the facilities provided by PowerShell. It seems there should be a way to create a class dynamically by extending the PSObject, PSProperty, and PSMethod classes described in the Powershell SDK.
Unfortunately the documentation around this seems pretty poor with a lot of ridiculous statements like "Although it is possible to derive from this class, there is no established scenario for doing this and any attempt to do so may result in unexpected behavior."
What made it worse is that all the links in MSDN explaining the PowerShell Extended Type System seem to be bad! And the only examples I've seen on the web is how to do this from a PowerShell script, not for people developing cmdlets using C# and the SDK.
Hello, anyone from the PowerShell team listening?
The ability to define your own new classes is something new they added in PowerShell v2. Here is a sample:
PS C:\> $def = @"
public class MyClass {
public string MyProperty;
}
"@
PS C:\> Add-Type -TypeDefinition $def
PS C:\> $obj = New-Object MyClass
PS C:\> $obj.MyProperty = "Hello"
PS C:\> $obj
MyProperty
----------
Hello
If you don't need something too complex, you might be able to take advantage of "splatting" - typically this is for producing name/value pairs for passing to cmdlets or functions, but it can work as kind of a generic object of sorts too:
PS C:\> $splat = @{
Name = "goyuix"
Site = "stackoverflow.com"
Tag = "powershell"
}
PS H:\> $splat
Name Value
---- -----
Name Goyuix
Site stackoverflow.com
Tag powershell
Take a look at the System.Reflection.Emit namespace. This will allow you to generate code at runtime. System.AppDomain has a number of overloads called DefineDynamicAssembly
which is typically where you would start. This returns an AssemblyBuilder
and from there you use types like TypeBuilder
, PropertyBuilder
, MethodBuilder
, etc. This CodeProject article is a decent primer on creating dynamic types with reflection emit.
I've been working on enhancing an implementation of PSClass.
Implementation source: https://github.com/ghostsquad/AetherClass/blob/master/functions/New-PSClass.ps1
Tests with usage: https://github.com/ghostsquad/AetherClass/blob/master/test/New-PSClass.Tests.ps1
There's also functionality to mock psclasses, which is to say, you get all the nifty functionality of Moq with a dynamic psobject.
精彩评论