2008-12-03 36 views
5

Tôi sử dụng tuần tự hóa XML để đọc Cấu hình-POCO của tôi.Nối tiếp và Lược đồ XML không có xsd.exe

Để nhận hỗ trợ intellisense trong Visual Studio cho tệp XML, tôi cần một tệp lược đồ. Tôi có thể tạo lược đồ với xsd.exe mylibrary.dll và nó hoạt động tốt.

Nhưng tôi muốn lược đồ luôn được tạo nếu tôi sắp xếp một đối tượng vào hệ thống tệp. Có cách nào mà không sử dụng xsd.exe?

Trả lời

11

cảm ơn bạn, đây là cách phù hợp với tôi. giải pháp:

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

Bây giờ tôi thấy mã của bạn, 'trông' những gì tôi đã quay lại (chỉ không thể nhớ lại ở đâu!) – leppie

11

Các giải pháp được đăng trên đây bởi Will làm việc tuyệt vời, ngoại trừ tôi nhận ra rằng giản đồ được tạo ra không phản ánh các thuộc tính về các thành viên lớp khác nhau. Ví dụ: một lớp được trang trí với các thuộc tính gợi ý tuần tự hóa (xem mẫu bên dưới), sẽ không hiển thị chính xác.

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; } 

    } 

Để giải quyết điều này, tôi đã tạo ra một vài chức năng helper mà dùng phản ánh để đi qua hệ thống phân cấp lớp, đọc các thuộc tính, và cư một đối tượng XmlAttributeOverrides có thể được chuyển vào XmlReflectionImporter.

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(); 
     } 
    } 

Hy vọng điều này sẽ giúp người khác.

+0

Làm thế nào để áp dụng đệ quy XmlAttributes cho các loại người dùng thuộc tính lồng nhau? Ví dụ: CustomerClass? –

0

Cải thiện phiên bản Matt Murrell: để áp dụng đệ quy XmlAttributes cho kiểu người dùng thuộc tính lồng nhau (ví dụ thuộc tính CustomerClass).

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; 
} 
Các vấn đề liên quan