當然,您可以在Powershell中定義一個類型,並在序列化中使用它。
第一步是定義一個新類型。在Powershell 2.0中,您可以通過 來調用Add-Type。一旦擁有包含新類型的動態編譯程序集,就可以像任何其他.NET類型一樣自由使用該類型。
第2步只是使用XmlSerializer類,就像您通常那樣 - 只是將您在問題中提供的C#代碼翻譯爲Powershell。
以下示例說明。它定義了一個簡單的類型,然後從XML字符串中反序列化以創建該類型的新實例。然後打印出該序列化的實例的屬性值。
$source1 = @"
using System;
using System.Xml;
using System.Xml.Serialization;
namespace MyDynamicTypes
{
[XmlRoot]
public class Foo
{
[XmlElement]
public string Message { get; set; }
[XmlAttribute]
public int Flavor { get; set; }
}
}
"@
Add-Type -TypeDefinition $source1 -Language "CSharpVersion3" -ReferencedAssemblies System.Xml.dll
$xml1 = @"
<Foo Flavor='19'>
<Message>Ephesians 5:11</Message>
</Foo>
"@
$f1 = New-Object MyDynamicTypes.Foo
$sr = New-Object System.IO.StringReader($xml1)
$s1 = New-Object System.Xml.Serialization.XmlSerializer($f1.GetType())
$xtr = New-Object System.Xml.XmlTextReader($sr)
$foo = $s1.Deserialize($xtr)
Write-Output ("foo.Flavor = " + $foo.Flavor)
Write-Output ("foo.Message = " + $foo.Message)
感謝Keith Hill指定添加類型。
在PowerShell 1.0中,你可以做一些自定義代碼(見Powershell: compiling c# code stored in a string)類似的東西。
function Compile-Code {
param (
[string[]] $code = $(throw "The parameter -code is required.")
, [string[]] $references = @()
, [switch] $asString = $false
, [switch] $showOutput = $false
, [switch] $csharp = $true
, [switch] $vb = $false
)
$options = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]";
$options.Add("CompilerVersion", "v3.5")
if ($vb) {
$provider = New-Object Microsoft.VisualBasic.VBCodeProvider $options
} else {
$provider = New-Object Microsoft.CSharp.CSharpCodeProvider $options
}
$parameters = New-Object System.CodeDom.Compiler.CompilerParameters
@("mscorlib.dll", "System.dll", "System.Core.dll", "System.Xml.dll", ([System.Reflection.Assembly]::GetAssembly([PSObject]).Location)) + $references | Sort -unique |% { $parameters.ReferencedAssemblies.Add($_) } | Out-Null
$parameters.GenerateExecutable = $false
$parameters.GenerateInMemory = !$asString
$parameters.CompilerOptions = "/optimize"
if ($asString) {
$parameters.OutputAssembly = [System.IO.Path]::GetTempFileName()
}
$results = $provider.CompileAssemblyFromSource($parameters, $code)
if ($results.Errors.Count -gt 0) {
if ($output) {
$results.Output |% { Write-Output $_ }
} else {
$results.Errors |% { Write-Error $_.ToString() }
}
} else {
if ($asString) {
$content = [System.IO.File]::ReadAllBytes($parameters.OutputAssembly)
$content = [Convert]::ToBase64String($content)
[System.IO.File]::Delete($parameters.OutputAssembly);
return $content
} else {
return $results.CompiledAssembly
}
}
}
使用該功能,應用程序就變成了:
$source1 = @"
using System;
using System.Xml;
using System.Xml.Serialization;
namespace MyDynamicTypes
{
[XmlRoot]
public class Foo
{
[XmlElement]
public string Message { get; set; }
[XmlAttribute]
public int Flavor { get; set; }
}
}
"@
Compile-Code -csharp -code $source1
$xml1 = @"
<Foo Flavor='19'>
<Message>Ephesians 5:11</Message>
</Foo>
"@
$f1 = New-Object MyDynamicTypes.Foo
$sr = New-Object System.IO.StringReader($xml1)
$s1 = New-Object System.Xml.Serialization.XmlSerializer($f1.GetType())
$xtr = New-Object System.Xml.XmlTextReader($sr)
$foo = $s1.Deserialize($xtr)
Write-Output ("foo.Flavor = " + $foo.Flavor)
Write-Output ("foo.Message = " + $foo.Message)
你會在哪裏拿'MyType'從如果不從程序集? YOu無法直接在PowerShell中定義類型;必須使用'Add-Type'。 – Joey 2010-05-05 19:04:07
這正是我的問題 - 有沒有辦法以某種方式在PowerShell中定義類型,然後將其用於序列化?根據你的回答,似乎沒有,因此必須在程序集中定義類型......真是一種痛苦 - 我想爲一個問題創建一個完整的基於腳本的解決方案而不需要程序集等。謝謝。 – Ariel 2010-05-05 19:09:09
「有沒有一種簡單的方法,像XmlSerializer,在PowerShell中序列化類型」Import/Export-CliXml應該可以正常工作。 – stej 2010-05-06 06:04:46