2011-03-18 11 views
7

Tengo algunos datos que obtengo de un origen de datos que es un conjunto de pares nombre/valor que almaceno en una cadena de diccionario , objeto >.Cómo definir dinámicamente una clase en C# Cmdlet PowerShell

Quiero definir una clase sobre la marcha, con propiedades que se relacionan con los pares clave/valor del diccionario y métodos basados ​​en el tipo de datos que representa. Esto permitiría al usuario del cmdlet acceder a los valores como propiedades de un objeto y también invocar métodos en él.

Veo un ejemplo de esto con Get-WmiObject. Devuelve instancias de ManagementObject (que básicamente es una bolsa de propiedades genérica) pero el usuario puede acceder a las propiedades e invocar métodos directamente (es decir, sin tener que llamar a los métodos GetPropertyValue/InvokeMethod en 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 ... 

¿Cómo puedo hacer esto con mis propios objetos?

ACTUALIZACIÓN

La aceptación de la respuesta de Keith, que es un enfoque del marco .NET general para la generación de código de forma dinámica. Esto debería funcionar para mi escenario, aunque creo que podría ser excesivo.

Esperaba que alguien proporcionara un claro ejemplo de cómo hacer esto usando las instalaciones proporcionadas por PowerShell. Parece que debería haber una manera de crear una clase dinámicamente ampliando las clases PSObject, PSProperty y PSMethod que se describen en el Powershell SDK.

Desafortunadamente la documentación sobre esto parece bastante pobre con muchas declaraciones ridículas como "Aunque es posible derivar de esta clase, no hay un escenario establecido para hacerlo y cualquier intento de hacerlo puede provocar un comportamiento inesperado "

¡Lo que empeora es que todos los enlaces en MSDN que explican el sistema de tipo extendido PowerShell parecen ser malos! Y los únicos ejemplos que he visto en la web es cómo hacerlo desde un script de PowerShell, no para personas que desarrollan cmdlets usando C# y el SDK.

Hola, ¿alguien del equipo de PowerShell está escuchando?

Respuesta

3

Tome un vistazo a la System.Reflection.Emit namespace. Esto te permitirá generar código en tiempo de ejecución. System.AppDomain tiene una cantidad de sobrecargas llamada DefineDynamicAssembly que suele ser donde comenzaría. Esto devuelve un AssemblyBuilder y desde allí se usan tipos como TypeBuilder, PropertyBuilder, MethodBuilder, etc. Este CodeProject article es un manual decente sobre cómo crear tipos dinámicos con reflexión emitida.

6

La capacidad de definir sus propias clases nuevas es algo nuevo que agregaron en PowerShell v2. Este es un ejemplo:

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 

Si no necesita algo demasiado complejo, que podría ser capaz de tomar ventaja de "splatting" - por lo general esto es para la producción de pares de nombre/valor para pasar a cmdlets o funciones, pero puede funcionar como una especie de objeto genérico de clases también:

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

PS H:\> $splat 

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

Estaba buscando una forma de hacerlo desde un Cmdlet escrito en C# usando el SDK de PowerShell. – DSO

+0

Acaba de probar: ** puede ** tener diferentes tipos de * valores * en símbolos, que pueden ser útiles. – Neolisk

0

He estado trabajando para mejorar una implementación de PSClass.

fuente de Implementación: https://github.com/ghostsquad/AetherClass/blob/master/functions/New-PSClass.ps1

Las pruebas con el uso: https://github.com/ghostsquad/AetherClass/blob/master/test/New-PSClass.Tests.ps1

También hay funcionalidad para psclasses simulados, es decir, se obtiene toda la funcionalidad ingeniosa de Moq con un psobject dinámico.

+0

Parece que estos enlaces han muerto, aunque el proyecto aún está activo. –

+1

Gracias, sí, he cambiado el nombre del paquete de módulos a Aether *. Actualización de enlaces. – wesm

Cuestiones relacionadas