如何在C#PowerShell Cmdlet中动态定义类

DSO*_*DSO 7 c# powershell powershell-2.0

我有一些数据来自数据源,这是一堆名称/值对,我存储在Dictionary <string,object>中.

我想动态定义一个类,其属性映射到字典中的键/值对,以及基于它所代表的数据类型的方法.这将允许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 ...
Run Code Online (Sandbox Code Playgroud)

我如何用自己的对象做到这一点?

UPDATE

接受Keith的答案,这是一种动态生成代码的通用.NET框架方法.这应该适用于我的场景,虽然我认为这可能是矫枉过正.

我希望有人能够使用PowerShell提供的功能提供一个明确的例子.似乎应该有一种通过扩展Powershell SDK中描述的PSObject,PSPropertyPSMethod类来动态创建类的方法.

不幸的是,围绕这个问题的文档似乎相当糟糕,有很多荒谬的陈述," 尽管可以从这个类派生出来,但没有确定的方法可以做到这一点,任何这样做的尝试都可能导致意外行为. "

更糟糕的是,MSDN中解释PowerShell扩展类型系统的所有链接似乎都很糟糕!我在网上看到的唯一例子是如何从PowerShell脚本执行此操作,而不是使用C#和SDK开发cmdlet的人.

您好,来自PowerShell团队的任何人都在倾听?

Goy*_*uix 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
Run Code Online (Sandbox Code Playgroud)

如果您不需要太复杂的东西,您可能可以利用"splatting" - 通常这是为了生成传递给cmdlet或函数的名称/值对,但它可以作为一种通用对象的类型工作太:

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

PS H:\> $splat

Name    Value
----    -----
Name    Goyuix
Site    stackoverflow.com
Tag     powershell
Run Code Online (Sandbox Code Playgroud)


Kei*_*ill 5

看一下System.Reflection.Emit 命名空间。这将允许您在运行时生成代码。System.AppDomain 有许多被调用的重载DefineDynamicAssembly,通常是您开始的地方。这会返回一个AssemblyBuilder,然后您可以使用TypeBuilderPropertyBuilderMethodBuilder等类型。这篇CodeProject 文章是关于使用反射发射创建动态类型的不错的入门读物。