具有ID和值以及名称的属性.我可以使用XmlElement / XmlArray C#注释代表所有具有单个类的人吗?我想从类属性名称派生xml元素名称;
我的课看起来像:
public class Property { public string name; //Could be enum public int ID; public string value;}
例如:
new Property("property1name",2,"testvalue");new Property("property2name",10,"anothervalue");
我想要xml看起来像:
<property1name><ID>2</ID><value>testvalue</value></property1name><property2name><ID>10</ID><value>anothervalue</value></property2name>
而不是通常的
<property><name>property1name</name><ID>2</ID><value>testvalue</value></property><property><name>property2name</name><ID>10</ID><value>anothervalue</value></property>
换句话说,xmlelement从类Property的属性名称中获取其名称
解决方法 更新这是一个快速适应处理您的Property类.首先,列表< T>实现IXmlSerializable
的子类:
public interface IHasElementname{ string Elementname { get; set; }}public class XmlnamedElementList<T> : List<T>,IXmlSerializable where T : IHasXmlElementname{ // https://msdn.microsoft.com/en-us/library/System.Xml.Serialization.XmlSerializer%28v=vs.110%29.aspx // Any serializer created with the "XmlSerializer(typeof(T),rootAttribute)" must be cached // to avoID resource & memory leaks. class ValueSerializerCache { // By using a nested class with a static constructor,we defer generation of the XmlSerializer until it's actually required. static ValueSerializerCache() { var rootAttribute = new XmlRootAttribute(); rootAttribute.Elementname = ValueTypename; rootAttribute.namespace = ValueTypenamespace; serializer = new XmlSerializer(typeof(T),rootAttribute); } static Readonly XmlSerializer serializer; internal static XmlSerializer Serializer { get { return serializer; } } } static string ValueTypename { get { return typeof(T).DefaultXmlElementname(); } } static string ValueTypenamespace { get { return typeof(T).DefaultXmlElementnamespace(); } } #region IXmlSerializable Members XmlSchema IXmlSerializable.GetSchema() { return null; } voID IXmlSerializable.readxml(XmlReader reader) { if (reader.IsEmptyElement) { reader.Read(); return; } var typename = ValueTypename; reader.ReadStartElement(); // Advance to the first sub element of the List element. while (reader.NodeType == XmlNodeType.Element) { var name = reader.name; using (var subReader = reader.ReadSubtree()) { var doc = Xdocument.Load(subReader); if (doc != null && doc.Root != null) { doc.Root.name = doc.Root.name.namespace + typename; using (var docReader = doc.CreateReader()) { var obj = ValueSerializerCache.Serializer.Deserialize(docReader); if (obj != null) { T value = (T)obj; value.Elementname = XmlConvert.Decodename(name); Add(value); } } } } // Move past the end of item element reader.Read(); } // Move past the end of the List element reader.ReadEndElement(); } voID IXmlSerializable.WriteXml(XmlWriter writer) { foreach (var value in this) { Xdocument doc = new Xdocument(); using (var subWriter = doc.CreateWriter()) { // write xml into the writer ValueSerializerCache.Serializer.Serialize(subWriter,value); } if (doc.Root == null) continue; doc.Root.name = doc.Root.name.namespace + XmlConvert.Encodename(value.Elementname); // Remove redundant namespaces. foreach (var attr in doc.Root.Attributes().ToList()) { if (!attr.IsnamespaceDeclaration || string.IsNullOrEmpty(attr.Value)) continue; var prefix = writer.LookupPrefix(attr.Value); if ((prefix == attr.name.Localname) || (prefix == string.Empty && attr.name == "xmlns")) attr.Remove(); } doc.Root.Writeto(writer); } } #endregion}public static class XmlSerializationHelper{ static Attribute GetCustomAttribute(MemberInfo element,Type attributeType) { return Attribute.GetCustomAttribute(element,attributeType); } static T GetCustomAttribute<T>(MemberInfo element) where T : Attribute { return (T)GetCustomAttribute(element,typeof(T)); } public static string DefaultXmlElementname(this Type type) { var xmlType = GetCustomAttribute<XmlTypeAttribute>(type); if (xmlType != null && !string.IsNullOrEmpty(xmlType.Typename)) return xmlType.Typename; var xmlRoot = GetCustomAttribute<XmlRootAttribute>(type); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.Elementname)) return xmlRoot.Elementname; return type.name; } public static string DefaultXmlElementnamespace(this Type type) { var xmlType = GetCustomAttribute<XmlTypeAttribute>(type); if (xmlType != null && !string.IsNullOrEmpty(xmlType.namespace)) return xmlType.namespace; var xmlRoot = GetCustomAttribute<XmlRootAttribute>(type); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.namespace)) return xmlRoot.namespace; return string.Empty; } public static string GetXml<T>(this T obj) { return GetXml(obj,false); } public static string GetXml<T>(this T obj,bool omitnamespace) { return GetXml(obj,new XmlSerializer(obj.GetType()),omitnamespace); } public static string GetXml<T>(this T obj,XmlSerializer serializer) { return GetXml(obj,serializer,false); } public static string GetXml<T>(T obj,XmlSerializer serializer,bool omitStandardnamespaces) { XmlSerializernamespaces ns = null; if (omitStandardnamespaces) { ns = new XmlSerializernamespaces(); ns.Add("",""); // disable the xmlns:xsi and xmlns:xsd lines. } return GetXml(obj,ns); } public static string GetXml<T>(T obj,XmlSerializernamespaces ns) { return GetXml(obj,XmlSerializernamespaces ns) { using (var textWriter = new StringWriter()) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; // For cosmetic purposes. settings.IndentChars = " "; // For cosmetic purposes. using (var xmlWriter = XmlWriter.Create(textWriter,settings)) { if (ns != null) serializer.Serialize(xmlWriter,obj,ns); else serializer.Serialize(xmlWriter,obj); } return textWriter.ToString(); } }}
并使用它像:
public class Property : IHasElementname{ public property() { } public Property(string name,int ID,string value) { this.name = name; this.ID = ID; this.value = value; } [Xmlignore] public string name; //Could be enum public int ID; public string value; #region IHasElementname Members [Xmlignore] string IHasElementname.Elementname { get { return name; } set { name = value; } } #endregion}public class RootObject{ public RootObject() { this.PropertIEs = new XmlnamedElementList<Property>(); } public XmlnamedElementList<Property> PropertIEs { get; set; }}public static class TestClass{ public static voID test() { var root = new RootObject { // Characters " <> first" in the first element name are for testing purposes. PropertIEs = new XmlnamedElementList<Property> { new Property { ID = 1,value = "1",name = "first" },new Property("property1name","testvalue"),new Property("property2name","anothervalue") } }; var xml = root.GetXml(); DeBUG.Writeline(xml); }}
其中生成XML如下:
<?xml version="1.0" enCoding="utf-16"?><RootObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <PropertIEs> <_x0020__x003C__x003E__x0020_first> <ID>1</ID> <value>1</value> </_x0020__x003C__x003E__x0020_first> <property1name> <ID>2</ID> <value>testvalue</value> </property1name> <property2name> <ID>10</ID> <value>anothervalue</value> </property2name> </PropertIEs></RootObject>
原始答案
根据要求,这是List< keyvaluePair< string,T>>上IXmlSerializable的实现.其中Key字符串成为集合中的元素名称.
您可能想要做的是调整它以序列化List< IHasElementname>哪里:
public interface IHasElementname{ string Elementname { get; set; }}public class Property : IHasElementname{ [Xmlignore] public string name; //Could be enum public int ID; public string value; #region IHasElementname Members [Xmlignore] string IHasElementname.Elementname { get { return name; } set { name = value; } } #endregion}
如果名称实际上是Enum,则可以从HasElementname.Elementname返回枚举字符串表示形式.
该列表如下:
public class XmlkeyvalueList<T> : List<keyvaluePair<string,T>>,IXmlSerializable{ // Todo: valIDate that the "Key" string using XmlConvert.Verifyname. // https://msdn.microsoft.com/en-us/library/System.Xml.Serialization.XmlSerializer%28v=vs.110%29.aspx // Any serializer created with the "XmlSerializer(typeof(T),rootAttribute); } static Readonly XmlSerializer serializer; internal static XmlSerializer Serializer { get { return serializer; } } } static string ValueTypename { get { return typeof(T).DefaultXmlElementname(); } } static string ValueTypenamespace { get { return typeof(T).DefaultXmlElementnamespace(); } } #region IXmlSerializable Members XmlSchema IXmlSerializable.GetSchema() { return null; } voID IXmlSerializable.readxml(XmlReader reader) { var typename = ValueTypename; reader.ReadStartElement(); // Advance to the first sub element of the List element. while (reader.NodeType == XmlNodeType.Element) { var name = reader.name; using (var subReader = reader.ReadSubtree()) { var doc = Xdocument.Load(subReader); if (doc != null && doc.Root != null) { doc.Root.name = typename; using (var docReader = doc.CreateReader()) { var obj = ValueSerializerCache.Serializer.Deserialize(docReader); if (obj != null) { Add(new keyvaluePair<string,T>(name,(T)obj)); } } } } // Move past the XmlNodeType.Element if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } } voID IXmlSerializable.WriteXml(XmlWriter writer) { foreach (var pair in this) { Xdocument doc = new Xdocument(); using (var subWriter = doc.CreateWriter()) { // write xml into the writer ValueSerializerCache.Serializer.Serialize(subWriter,pair.Value); } if (doc.Root == null) continue; doc.Root.name = pair.Key; // Remove redundant namespaces. foreach (var attr in doc.Root.Attributes().ToList()) { if (!attr.IsnamespaceDeclaration || string.IsNullOrEmpty(attr.Value)) continue; if (writer.LookupPrefix(attr.Value) == attr.name.Localname) attr.Remove(); } doc.Root.Writeto(writer); } } #endregion}public static class XmlSerializationHelper{ public static string DefaultXmlElementname(this Type type) { var xmlType = type.GetCustomAttribute<XmlTypeAttribute>(); if (xmlType != null && !string.IsNullOrEmpty(xmlType.Typename)) return xmlType.Typename; var xmlRoot = type.GetCustomAttribute<XmlRootAttribute>(); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.Elementname)) return xmlRoot.Elementname; return type.name; } public static string DefaultXmlElementnamespace(this Type type) { var xmlType = type.GetCustomAttribute<XmlTypeAttribute>(); if (xmlType != null && !string.IsNullOrEmpty(xmlType.namespace)) return xmlType.namespace; var xmlRoot = type.GetCustomAttribute<XmlRootAttribute>(); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.namespace)) return xmlRoot.namespace; return string.Empty; }}总结
以上是内存溢出为你收集整理的c# – 如何使用注释从类的属性值派生xml元素名称?全部内容,希望文章能够帮你解决c# – 如何使用注释从类的属性值派生xml元素名称?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)