[英]XML Serialization and Schema without xsd.exe
I use XML serialization for the reading of my Config-POCOs. 我使用XML序列化来读取我的Config-POCO。
To get intellisense support in Visual Studio for XML files I need a schema file. 要在Visual Studio中获取XML文件的智能感知支持,我需要一个模式文件。 I can create the schema with xsd.exe mylibrary.dll and this works fine. 我可以用xsd.exe mylibrary.dll创建架构,这很好用。
But I want that the schema is always created if I serialize an object to the file system. 但是,如果我将对象序列化到文件系统,我希望始终创建模式。 Is there any way without using xsd.exe? 没有使用xsd.exe有什么办法吗?
The solution posted above by Will worked wonderfully, except I realized that the schema generated did not reflect the attributes on the different class members. Will上面发布的解决方案效果很好,除了我意识到生成的模式没有反映不同类成员的属性。 For example a class decorated with serialization hint attributes (see the sample below), would have not rendered correctly. 例如,使用序列化提示属性修饰的类(请参阅下面的示例)将无法正确呈现。
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; }
}
To address this, I created a few helper functions that use reflection to traverse the class hierarchy, read the attributes, and populate a XmlAttributeOverrides object that can be passed into the XmlReflectionImporter. 为了解决这个问题,我创建了一些帮助函数,它们使用反射来遍历类层次结构,读取属性,并填充可以传递给XmlReflectionImporter的XmlAttributeOverrides对象。
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();
}
}
Hope this helps someone else. 希望这有助于其他人。
thank you, this was the right way for me. 谢谢,这对我来说是正确的方式。 solution: 解:
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();
Look at the System.Xml.Serialization.XmlSchemaExporter
class. 查看System.Xml.Serialization.XmlSchemaExporter
类。 I can't recall the exact details, but there is enough functionality in that namespace to do what you require. 我无法回想起确切的细节,但是在该命名空间中有足够的功能可以满足您的需求。
Improvement to Matt Murrell version: to apply XmlAttributes recursively for nested property user type (for example CustomerClass property). 对Matt Murrell版本的改进:递归地为嵌套属性用户类型应用XmlAttributes(例如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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.