2008-12-03 10 views
5

Ich verwende XML-Serialisierung für das Lesen meiner Config-POCOs.XML-Serialisierung und Schema ohne xsd.exe

Um Intellisense-Unterstützung in Visual Studio für XML-Dateien zu erhalten, brauche ich eine Schemadatei. Ich kann das Schema mit xsd.exe mylibrary.dll erstellen und das funktioniert gut.

Aber ich möchte, dass das Schema immer erstellt wird, wenn ich ein Objekt in das Dateisystem serialisieren. Gibt es eine Möglichkeit, ohne xsd.exe zu verwenden?

Antwort

11

danke, das war der richtige Weg für mich. Lösung:

XmlReflectionImporter importer = new XmlReflectionImporter(); 
XmlSchemas schemas = new XmlSchemas(); 
XmlSchemaExporter exporter = new XmlSchemaExporter(schemas); 
Type type = toSerialize.GetType(); 
XmlTypeMapping map = importer.ImportTypeMapping(type); 
exporter.ExportTypeMapping(map); 

TextWriter tw = new StreamWriter(fileName + ".xsd"); 
schemas[0].Write(tw); 
tw.Close(); 
+0

Nun, da ich Sie Code zu sehen, es sieht ", was ich zurück tat (einfach nicht erinnern, wo!) – leppie

11

Die Lösung oben von Will geschrieben hat wunderbar funktioniert, außer ich, dass das Schema erzeugt realisiert nicht die Attribute auf den verschiedenen Klassenmitglieder widerspiegelten. Eine Klasse, die mit Serialisierungshinweisattributen versehen ist (siehe Beispiel unten), wäre beispielsweise nicht korrekt gerendert worden.

public class Test 
    { 
     [XmlAttribute()] 
     public string Attribute { get; set; } 
     public string Description { get; set; } 

     [XmlArray(ElementName = "Customers")] 
     [XmlArrayItem(ElementName = "Customer")] 
     public List<CustomerClass> blah { get; set; } 

    } 

dies zu beheben, habe ich ein paar Hilfsfunktionen, die Reflektion verwenden, um die Klassenhierarchie, lesen Sie die Attribute, und füllen Sie eine XmlAttributeOverrides Objekt zu durchqueren, die in die XmlReflectionImporter geben werden kann.

public static void AttachXmlAttributes(XmlAttributeOverrides xao, Type t) 
    { 
     List<Type> types = new List<Type>(); 
     AttachXmlAttributes(xao, types, t); 
    } 

    public static void AttachXmlAttributes(XmlAttributeOverrides xao, List<Type> all, Type t) 
    { 
     if(all.Contains(t)) 
      return; 
     else 
      all.Add(t); 

     XmlAttributes list1 = GetAttributeList(t.GetCustomAttributes(false)); 
     xao.Add(t, list1); 

     foreach (var prop in t.GetProperties()) 
     { 
      XmlAttributes list2 = GetAttributeList(prop.GetCustomAttributes(false)); 
      xao.Add(t, prop.Name, list2); 
      AttachXmlAttributes(xao, all, prop.PropertyType); 
     } 
    } 

    private static XmlAttributes GetAttributeList(object[] attributes) 
    { 
     XmlAttributes list = new XmlAttributes(); 
     foreach (var attribute in attributes) 
     { 
      Type type = attribute.GetType(); 
      if (type.Name == "XmlAttributeAttribute") list.XmlAttribute = (XmlAttributeAttribute)attribute; 
      else if (type.Name == "XmlArrayAttribute") list.XmlArray = (XmlArrayAttribute)attribute; 
      else if (type.Name == "XmlArrayItemAttribute") list.XmlArrayItems.Add((XmlArrayItemAttribute)attribute); 

     } 
     return list; 
    } 
    public static string GetSchema<T>() 
    { 
     XmlAttributeOverrides xao = new XmlAttributeOverrides(); 
     AttachXmlAttributes(xao, typeof(T)); 

     XmlReflectionImporter importer = new XmlReflectionImporter(xao); 
     XmlSchemas schemas = new XmlSchemas(); 
     XmlSchemaExporter exporter = new XmlSchemaExporter(schemas); 
     XmlTypeMapping map = importer.ImportTypeMapping(typeof(T)); 
     exporter.ExportTypeMapping(map); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      schemas[0].Write(ms); 
      ms.Position = 0; 
      return new StreamReader(ms).ReadToEnd(); 
     } 
    } 

Hoffe das hilft jemand anderen.

+0

Wie XmlAttributes rekursiv für verschachtelte Eigenschaft Benutzertypen anwenden? Zum Beispiel CustomerClass? –

0

Verbesserung zu Matt Murrell-Version: XmlAttributes rekursiv für verschachtelte Eigenschaft Benutzertyp (z. B. CustomerClass-Eigenschaft) anwenden.

private static void AttachXmlAttributes(XmlAttributeOverrides xao, List<Type> all, Type t) 
{ 
    if (all.Contains(t)) 
    { 
     return; 
    } 
    else 
    { 
     all.Add(t); 
    } 

    var list1 = GetAttributeList(t.GetCustomAttributes(false)); 
    xao.Add(t, list1); 

    foreach (var prop in t.GetProperties()) 
    { 
     var propType = prop.PropertyType; 
     if (propType.IsGenericType) // is list? 
     { 
      var args = propType.GetGenericArguments(); 
      if (args != null && args.Length == 1) 
      {       
       var genType = args[0]; 
       if (genType.Name.ToLower() != "object") 
       { 
        var list2 = GetAttributeList(prop.GetCustomAttributes(false)); 
        xao.Add(t, prop.Name, list2); 
        AttachXmlAttributes(xao, all, genType); 
       }       
      } 
     } 
     else 
     { 
      var list2 = GetAttributeList(prop.GetCustomAttributes(false)); 
      xao.Add(t, prop.Name, list2); 
      AttachXmlAttributes(xao, all, prop.PropertyType); 
     } 
    } 
}   

private static XmlAttributes GetAttributeList(object[] attributes) 
{ 
    var list = new XmlAttributes(); 
    foreach (var attr in attributes) 
    { 
     Type type = attr.GetType(); 
     switch (type.Name) 
     { 
      case "XmlAttributeAttribute": 
       list.XmlAttribute = (XmlAttributeAttribute)attr; 
       break;      
      case "XmlRootAttribute": 
       list.XmlRoot = (XmlRootAttribute)attr; 
       break; 
      case "XmlElementAttribute": 
       list.XmlElements.Add((XmlElementAttribute)attr); 
       break; 
      case "XmlArrayAttribute": 
       list.XmlArray = (XmlArrayAttribute)attr; 
       break; 
      case "XmlArrayItemAttribute": 
       list.XmlArrayItems.Add((XmlArrayItemAttribute)attr); 
       break; 
     } 
    } 
    return list; 
} 
Verwandte Themen