【问题标题】:How to dynamically define a class in C# PowerShell Cmdlet如何在 C# PowerShell Cmdlet 中动态定义一个类
【发布时间】:2011-03-18 17:05:19
【问题描述】:

我从数据源中获取了一些数据,这些数据是我存储在 Dictionary 中的一堆名称/值对。

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

如何使用我自己的对象执行此操作?

更新

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

我希望有人能提供一个使用 PowerShell 提供的工具执行此操作的明确示例。似乎应该有一种方法可以通过扩展Powershell SDK 中描述的PSObjectPSPropertyPSMethod 类来动态创建类。

不幸的是,有关此的文档似乎很差,有很多荒谬的陈述,例如“尽管可以从此类派生,但没有既定的场景可以这样做,任何尝试这样做都可能导致意外行为。"

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

您好,PowerShell 团队有人在听吗?

【问题讨论】:

    标签: c# powershell powershell-2.0


    【解决方案1】:

    定义您自己的新类的能力是他们在 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
    

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

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

    【讨论】:

    • 我正在寻找一种方法来通过使用 PowerShell SDK 用 C# 编写的 Cmdlet 来执行此操作。
    • 刚刚测试过 - 你可以在 splats 中有不同类型的 ,这可能很有用。
    【解决方案2】:

    看看System.Reflection.Emit namespace。这将允许您在运行时生成代码。 System.AppDomain 有许多称为DefineDynamicAssembly 的重载,这通常是您开始的地方。这将返回一个AssemblyBuilder,然后您可以从那里使用TypeBuilderPropertyBuilderMethodBuilder 等类型。这个CodeProject article 是关于使用反射发射创建动态类型的不错入门。

    【讨论】:

      【解决方案3】:

      我一直致力于增强 PSClass 的实现。

      实现来源: https://github.com/ghostsquad/AetherClass/blob/master/functions/New-PSClass.ps1

      使用测试: https://github.com/ghostsquad/AetherClass/blob/master/test/New-PSClass.Tests.ps1

      还有模拟 psclass 的功能,也就是说,您可以通过动态 psobject 获得 Moq 的所有漂亮功能。

      【讨论】:

      • 这些链接似乎已经失效,但该项目仍然存在。
      • 谢谢,是的,我已将模块套件重命名为 Aether*。正在更新链接。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 2018-12-07
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多