2017-05-09 1 views
3

Ich muss die XML-Zeichenfolge in List konvertieren, sollte die Methode generisch sein. Ich habe eine Methode geschrieben, die aber nicht wie erwartet funktioniert.XML-String in Liste konvertieren <T> ohne Angabe von Element Root in C#

Szenario: # 1

Model-Klasse:

public class Employee { 
    public int EmpId { get; set; } 
    public string Name { get; set; } 
} 

XML:

<EmployeeList 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Employee> 
     <EmpId>1</EmpId> 
     <Name>Emma</Name> 
    </Employee> 
    <Employee> 
     <EmpId>2</EmpId> 
     <Name>Watson</Name> 
    </Employee> 
</EmployeeList> 

Szenario: # 2

Model-Klasse:

public class Person { 
    public int PersonId { get; set; } 
    public string Name { get; set; } 
} 

XML:

<PersonList 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Person> 
     <PersonId>1</EmpId> 
     <Name>Emma</Name> 
    </Person> 
    <Person> 
     <PersonId>2</EmpId> 
     <Name>Watson</Name> 
    </Person> 
</PersonList> 

Ich brauche eine generische Methode, die oben zu konvertieren die XML ist zu List<Employee> und List<Person>.

habe ich den folgenden Code

public static T[] ParseXML<T>(this string @this) where T : class { 
    var reader = XmlReader.Create(@this.Trim().ToStream(),new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document }); 
    return new XmlSerializer(typeof(T[])).Deserialize(reader) as T[]; 
} 

Aber ich bin NULL bekommen. Bitte helfen Sie mir, damit umzugehen.

Ich habe viel Code referenziert, aber sie sagen, das Root-Element als fest codierten Wert anzugeben. Aber ich brauche eine generische Methode.

Die Signatur sollte in dieser Hinsicht

public static T[] ParseXML<T>(this string @this) where T : class { } 

Bitte helfen Sie mir sein.

Antwort

2

Der Standard-Root-Name ist ArrayOfThing, nicht ThingList, so dass Sie den Serializer sagen müssen:

var ser = new XmlSerializer(list.GetType(), new XmlRootAttribute("EmployeeList")); 

aber Sie müssen auch zwischenspeichern und wieder verwenden diese Baugruppe Speicherlecks zu verhindern (Nur die einfachsten Konstruktoren werden automatisch zwischengespeichert). Ein statisches Nur-Lese-Feld auf einem generischen Typ ist eine gute Wette, zum Beispiel:

static class SerializerCache<T> { 
    public static readonly XmlSerializer Instance = new XmlSerializer(
     typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "List")); 
} 

dann SerializerCache<T>.Instance anstelle von new XmlSerializer

Offensichtlich tauschen Listen und Arrays, wenn Sie mögen ...

+0

@Mastero alles, was ich erwähnt habe, nach innen * Ihrer vorhandenen 'ParseXML' Methode * happen, so: keine Änderung erforderlich - nur die letzte Zeile von' ParseXML' würde 'SerializerCache .Instance' anstelle von' new XmlSerializer (...) ' –

+0

Ja, ich habe es. Vielen Dank... –

0

Ich leitete die Antwort von Marc Gravell - Convert XML string to List<T> without specifiying Element Root in C#, die ich als richtig markiert wurde.

public static class SerializerCache<T> { 
    public static readonly XmlSerializer Instance = new XmlSerializer(
     typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "List")); 
} 

public static class XMLHelper { 

    public static List<T> ParseXML<T>(this string @this) where T : class { 

     XmlSerializer serializer = SerializerCache<T>.Instance; 
     MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(@this)); 

     if(!string.IsNullorEmpty(@this) && (serializer != null) && (memStream != null)) { 
      return serializer.Deserialize(memStream) as List<T>; 
     } 
     else { 
      return null; 
     } 
    } 
} 

Die wichtigste Methode ist sieht aus wie

public static List<Employee> GetEmployeeList(string xml) { 
    return xml.ParseXML<Employee>(); 
} 
Verwandte Themen