2013-03-13 21 views
11

Ho uno schema XML .xsd e generare con lo strumento xsd.exe il mio file con tutte le classi C#. Se ho una sequenza di elementi all'interno di un tag XML, ciò sarebbe rappresentato in C# con una matrice. Il FAIL è ovvio. Come posso generare liste invece di matrici?come generare lista invece di matrice in C# con xsd.exe

Invece di matrici di dimensioni fisse in una classe, mi piacerebbe utilizzare le liste.

Book [] books = new Book[someFixSize]; 

List<Book> books = new List<Book>(); 

Ho visto alcuni anziani (molto vecchi) domande su questo, ma nessuno di loro fornito una soluzione soddisfatta:/

Questo è l'ultimo suggerimento utile: http://www.stefanbader.ch/xsdcsarr2l-exe-refactor-xsd-array-to-list/

risposta

6

mi imbatto nello stesso problema cercando di utilizzare lo svcutil senza avere i contratti, per questo motivo ho scritto il xsdcsarr2l troppo l. Se sei interessato, prendo tempo e carica una versione più recente in cui almeno le variabili di lista vengono inizializzate automaticamente. D'altra parte, il progetto è abbastanza leggero, che puoi prendere la fonte e migliorarla da solo usando le classi NRefactory.

+0

Sei semplice sostituire la linea che contiene una matrice [] con una lista ? Oppure vengono modificate anche altre righe del codice? – Gero

+0

Solo le linee in cui sono coinvolti gli array fissi. Lo strumento sta analizzando il C# -source e trasferendolo in un AST (Abstract Syntax Tree) con l'aiuto di NRefactory. Quindi i cambiamenti sono applicati in modo robusto. L'idea era di toccare il meno possibile dell'originale. – EvilBad

+0

sì, carica l'ultima versione. – Gero

2

Provare a usare svcutil. exe

svcutil /o:myFile.cs /ct:System.Collections.Generic.List myXsd.xsd 
+1

non ho Datacontracts nel mio XSD, quindi svcutil non funzionerà – Gero

+0

Credo che l'unica opzione è quella di refactoring manualmente il codice generato automaticamente. – CathalMF

0

Prova Xsd2Code

che genera liste invece di array. Sfortunatamente non sono riuscito a deserializzare il mio codice, ma confrontandolo con il codice generato da xsd sembrava molto simile.

+0

nov2015 - Il venditore xsd2code non risponde affatto. Non è possibile ottenere una licenza di prova e l'e-mail rimbalza. Penso che questo sia abbandonato. –

0

Mi sono imbattuto nello stesso problema di recente, l'unica ragione per cui volevo List invece di T [] era perché volevo aggiungere elementi all'array prima di inviare una richiesta a un servizio web. Ho usato il fatto che xsd.exe genera una classe parziale. È possibile aggiungere la propria classe parziale aggiungendo un costruttore e un metodo ADDT che utilizzerà Array.Resize() prima di assegnare al (nuovo) ultimo elemento. Non è necessario modificare il codice generato o utilizzare un altro strumento.

0

Dan Field ha un powershell script che accetta una classe di output xsd.exe e trasforma i suoi array in elenchi generici. Questo ha funzionato bene per me con una classe semplice, ma non so quanto bene scala. Ho incollato la sceneggiatura qui sotto. Chiama da un prompt dei comandi come questo

"$(TargetFrameworkSDKToolsDirectory)xsd.exe" /c "$(ProjectDir)ImportedPartCanonical.xsd" "$(ProjectDir)ProjectCanonical.xsd" /n:Tallan.BT.PipelineComponents 

powershell.exe -ExecutionPolicy Unrestricted -file "$(solutiondir)\PowerShellScripts\PostProcessXsdExe.ps1" ProjectCanonical.cs "$(SolutionDir)Tallan.BT.PipelineComponents\SerializedClasses\ProjectCanonical.cs" 

Vedere il link per la spiegazione completa.

# Author: Dan Field ([email protected]) 
# posted on blog.tallan.com/2016/03/10/xsd-exe-arrays-and-specified 
# Purpose: fix the 'specified' attribute and convert arrays to list from XSD.exe generated classes 

[CmdletBinding()] 
Param(
    [Parameter(Mandatory=$true,Position=1)] 
    [string]$inputFile, 
    [Parameter(Mandatory=$true,Position=2)] 
    [string]$outputFile, 
    [switch]$DeleteInputFile 
) 

# much faster than using Get-Content and/or Out-File/Set-Content 
$writer = [System.IO.StreamWriter] $outputFile 
$reader = [System.IO.StreamReader] $inputFile 

# used to track Specified properties 
$setterDict = @{} 

while (($line = $reader.ReadLine()) -ne $null) 
{ 
    $thisStart = $line.IndexOf("this.") # will be used for 
    $brackets = $line.IndexOf("[]") # indicates an array that will be converted to a Generic List 

    # assume that any private field that contains "Specified" needs to be grabbed 
    if (($line.IndexOf("private") -gt -1) -and ($line.IndexOf("Specified") -gt -1)) 
    { 
     # get the field name 
     $varName = $line.Split("{' ',';'}", [System.StringSplitOptions]::RemoveEmptyEntries)[-1] 
     # use field name as a key, minus the ending "Specified" portion, e.g. fieldNameSpecified -> fieldName 
     # the value in the dictionary will be added to setters on the main property, e.g. "this.fieldNameSpecified = true;" 
     $setterDict.Add($varName.Substring(0, $varName.IndexOf("Specified")), "this." + $varName + " = true;") 
     # output the line as is 
     $writer.WriteLine($line) 
    } 
    # find property setters that aren't for the *Specified properties 
    elseif (($thisStart -gt -1) -and ($line.IndexOf(" = value") -gt -1) -and ($line.IndexOf("Specified") -lt 0)) 
    { 
     # get the field name 
     $thisStart += 5 
     $varName = $line.Substring($thisStart, $line.IndexOf(' ', $thisStart) - $thisStart) 
     # see if there's a "Specified" property for this one 
     if ($setterDict.ContainsKey($varName) -eq $true) 
     { 
      # set the Specified property whenever this property is set 
      $writer.WriteLine((' ' * ($thisStart - 5)) + $setterDict[$varName]) 
     } 
     # output the line itself 
     $writer.WriteLine($line) 
    } 
    elseif ($brackets -gt 0) # change to List<T> 
    { 
     $lineParts = $line.Split(' ') 
     foreach ($linePart in $lineParts) 
     { 
      if ($linePart.Contains("[]") -eq $true) 
      { 
       $writer.Write("System.Collections.Generic.List<" + $linePart.Replace("[]", "> ")) 
      } 
      else 
      { 
       $writer.Write($linePart + " ") 
      } 
     } 
     $writer.WriteLine(); 
    } 
    else # just output the original line 
    { 
     $writer.WriteLine($line) 
    } 
} 

if ($DeleteInputFile -eq $true) 
{ 
    Remove-Item $inputFile 
}  

# Make sure the file gets fully written and clean up handles 
$writer.Flush(); 
$writer.Dispose(); 
$reader.Dispose();