2011-03-18 89 views
7

我有一些數據,我從一個數據源獲得的是一串名稱/值對,我存儲在一個字典<字符串,對象>。如何在C#中PowerShell Cmdlet的動態定義類

我想動態地定義一個類,其屬性映射到字典中的鍵/值對和基於它所表示的數據類型的方法。這將允許cmdlet的用戶作爲對象的屬性訪問這些值,並調用其上的方法。

我用Get-WmiObject看到了這個例子。它返回ManagementObject的實例(基本上它是一個通用的屬性包),但用戶可以直接訪問屬性並調用它的方法(即不必調用ManagementObject上的GetPropertyValue/InvokeMethod方法)。

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 ... 

我該如何處理自己的物體?

UPDATE

接受基思的答案是動態生成代碼的通用.NET框架的方法。這應該適用於我的場景,儘管我認爲這可能是矯枉過正。

我曾希望有人會提供一個使用PowerShell提供的工具來完成此操作的明確示例。看起來應該有一種方法可以通過擴展Powershell SDK中描述的PSObject,PSPropertyPSMethod類來動態創建類。

不幸的是,圍繞這個的文檔似乎很差,有很多荒謬的陳述,比如「儘管可以從這個類派生,但是沒有確定的方案來做到這一點,並且任何嘗試這樣做都可能導致意外的行爲

更糟糕的是,MSDN中解釋PowerShell擴展類型系統的所有鏈接似乎都很糟糕!我在網上看到的唯一示例是如何從PowerShell腳本執行此操作,而不是使用C#和SDK開發cmdlet的人員。

你好,任何來自PowerShell團隊的人都在聽嗎?

回答

3

看一看System.Reflection.Emit namespace。這將允許您在運行時生成代碼。 System.AppDomain有一些稱爲DefineDynamicAssembly的重載,這通常是您要啓動的位置。這將返回一個AssemblyBuilder,並從那裏使用類型如TypeBuilderPropertyBuilder,MethodBuilder等。此CodeProject article是創建具有反射發射的動態類型的體面入門書。

6

定義自己的新類的能力是他們在PowerShell v2中添加的新東西。下面是一個示例:

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 

如果你不需要的東西太複雜,你也許可以採取「潑灑」的優勢 - 通常這是用於生產的名稱/值對傳遞給cmdlet的或功能,但它也可以作爲一種通用對象:

PS C:\> $splat = @{ 
    Name = "goyuix" 
    Site = "stackoverflow.com" 
    Tag = "powershell" 
} 

PS H:\> $splat 

Name Value 
---- ----- 
Name Goyuix 
Site stackoverflow.com 
Tag  powershell 
+1

我正在尋找一種方法來從使用PowerShell SDK編寫的C#Cmdlet中執行此操作。 – DSO 2011-03-18 19:25:12

+0

剛剛經過測試 - 你可以在splats中爲* values *設置不同的類型,這可能有用。 – Neolisk 2013-04-12 12:14:29

0

我一直在努力增強PSClass的實現。

實現來源: https://github.com/ghostsquad/AetherClass/blob/master/functions/New-PSClass.ps1

測試與用法: https://github.com/ghostsquad/AetherClass/blob/master/test/New-PSClass.Tests.ps1

還有功能模擬psclasses,這是說,你起訂量的所有漂亮的功能與動態psobject。

+0

儘管該項目還活着,但這些鏈接似乎已經死亡。 – 2015-04-07 14:58:16

+1

謝謝,是的,我已將模塊套件更名爲Aether *。更新鏈接。 – wesm 2015-04-08 16:20:55

相關問題