Ответ 1
Тип XmlSerializer
не предлагает ничего XmlSerializer
для обработки этого.
Если вам действительно нужно использовать XmlSerializer
, вы в конечном итоге получите пользовательскую реализацию XmlSerializer
, которая не совсем открыта для расширения. По этой причине реализация ниже является скорее доказательством концепции, просто чтобы дать вам идею или отправную точку.
Для краткости я пропустил обработку ошибок и только сосредоточился на классе Person
в вашем вопросе. Для обработки любых вложенных сложных свойств еще предстоит выполнить некоторую работу.
Поскольку методы Serialize
не являются virtual
нам придется их затенять. Основная идея заключается в том, чтобы перенаправить все перегрузки на один, имеющий пользовательскую реализацию.
Из-за настройки мы должны быть более явными в классе Person
при написании элементов xml для своих свойств, указав пространство имен xml, которое будет применяться.
Код ниже
PrefixedXmlSerializer xmlSerializer = new PrefixedXmlSerializer(typeof(Person));
Person person = new Person {
FirstName = "John",
LastName = "Doe"
};
xmlSerializer.Serialize(Console.Out, person, person.Namespaces);
приводит к
<My:person xmlns:My="MyNamespace">
<My:firstName>John</My:firstName>
<My:lastName>Doe</My:lastName>
</My:person>
Вам решать, приемлемо ли это все.
В конце концов, <My:person xmlns:My="MyNamespace">
equals <person xmlns="MyNamespace">
.
Человек
[XmlRoot(ElementName = "person", Namespace = NAMESPACE)]
public class Person : IXmlSerializable
{
private const string NAMESPACE = "MyNamespace";
public string FirstName { get; set; }
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces Namespaces
{
get
{
var xmlSerializerNamespaces = new XmlSerializerNamespaces();
xmlSerializerNamespaces.Add("My", NAMESPACE);
return xmlSerializerNamespaces;
}
}
public string LastName { get; set; }
public XmlSchema GetSchema()
{
return null;
}
/// <exception cref="NotSupportedException"/>
public void ReadXml(XmlReader reader)
{
throw new NotSupportedException();
}
public void WriteXml(XmlWriter writer)
{
// Specify the xml namespace.
writer.WriteElementString("firstName", NAMESPACE, FirstName);
writer.WriteElementString("lastName", NAMESPACE, LastName);
}
}
PrefixedXmlSerializer
public class PrefixedXmlSerializer : XmlSerializer
{
XmlRootAttribute _xmlRootAttribute;
public PrefixedXmlSerializer(Type type) : base(type)
{
this._xmlRootAttribute = type.GetCustomAttribute<XmlRootAttribute>();
}
public new void Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces)
{
// Out-of-the-box implementation.
XmlTextWriter xmlTextWriter = new XmlTextWriter(textWriter);
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.Indentation = 2;
// Call the shadowed version.
this.Serialize(xmlTextWriter, o, namespaces, null, null);
}
public new void Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
{
// Lookup the xml namespace and prefix to apply.
XmlQualifiedName[] xmlNamespaces = namespaces.ToArray();
XmlQualifiedName xmlRootNamespace =
xmlNamespaces
.Where(ns => ns.Namespace == this._xmlRootAttribute.Namespace)
.FirstOrDefault();
// Write the prefixed root element with its xml namespace declaration.
xmlWriter.WriteStartElement(xmlRootNamespace.Name, this._xmlRootAttribute.ElementName, xmlRootNamespace.Namespace);
// Write the xml namespaces; duplicates will be taken care of automatically.
foreach (XmlQualifiedName xmlNamespace in xmlNamespaces)
{
xmlWriter.WriteAttributeString("xmlns", xmlNamespace.Name , null, xmlNamespace.Namespace);
}
// Write the actual object xml.
((IXmlSerializable)o).WriteXml(xmlWriter);
xmlWriter.WriteEndElement();
}
}