没有xsd.exe的XML序列化和架构

我使用XML序列化来读取我的Config-POCO。

要在Visual Studio中获取XML文件的智能感知支持,我需要一个模式文件。 我可以用xsd.exe mylibrary.dll创建架构,这很好用。

但是,如果我将对象序列化到文件系统,我希望始终创建模式。 没有使用xsd.exe有什么办法吗?

查看System.Xml.Serialization.XmlSchemaExporter类。 我无法回想起确切的细节,但是该命名空间中有足够的function可以满足您的需求。

谢谢,这对我来说是正确的方式。 解:

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

Will上面发布的解决方案效果很好,除了我意识到生成的模式没有反映不同类成员的属性。 例如,使用序列化提示属性修饰的类(请参阅下面的示例)将无法正确呈现。

  public class Test { [XmlAttribute()] public string Attribute { get; set; } public string Description { get; set; } [XmlArray(ElementName = "Customers")] [XmlArrayItem(ElementName = "Customer")] public List blah { get; set; } } 

为了解决这个问题,我创建了一些辅助函数,它们使用reflection来遍历类层次结构,读取属性,并填充可以传递给XmlReflectionImporter的XmlAttributeOverrides对象。

  public static void AttachXmlAttributes(XmlAttributeOverrides xao, Type t) { List types = new List(); AttachXmlAttributes(xao, types, t); } public static void AttachXmlAttributes(XmlAttributeOverrides xao, List 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() { 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(); } } 

希望这有助于其他人。

对Matt Murrell版本的改进:以递归方式为嵌套属性用户类型(例如CustomerClass属性)应用XmlAttributes。

 private static void AttachXmlAttributes(XmlAttributeOverrides xao, List 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; }