Начальный вопрос
Я хочу serialize
и List<IXmlSerializable>
динамически изменять XmlType класса IXmlSerializable
(поэтому я не могу использовать теги атрибутов для этого)
Я пытался использовать XmlAttributeOverrides, чтобы сделать это, пока безуспешно.
Вот пример кода, иллюстрирующий проблему:
Класс IXmlSerializable (из MSDN):
public class Person : IXmlSerializable
{
// Private state
private string personName;
// Constructors
public Person(string name)
{
personName = name;
}
public Person()
{
personName = null;
}
// Xml Serialization Infrastructure
public void WriteXml(XmlWriter writer)
{
writer.WriteString(personName);
}
public void ReadXml(XmlReader reader)
{
personName = reader.ReadString();
}
public XmlSchema GetSchema()
{
return (null);
}
// Print
public override string ToString()
{
return (personName);
}
}
Тестовый класс (с использованием консоли для вывода):
class Program
{
static void Main(string[] args)
{
List<Person> lPersonList = new List<Person> {
new Person("First"),
new Person("Second"),
new Person("Third")
};
XmlAttributeOverrides lOverrides = new XmlAttributeOverrides();
XmlAttributes lAttributes = new XmlAttributes { XmlType = new XmlTypeAttribute("Employee") };
lOverrides.Add(typeof(Person), lAttributes);
XmlSerializer lSerialiser = new XmlSerializer(typeof(List<Person>), lOverrides, null, new XmlRootAttribute("Employees"), null);
XmlSerializerNamespaces lNamespaces = new XmlSerializerNamespaces();
lNamespaces.Add("", "");
lSerialiser.Serialize(Console.Out, lPersonList, lNamespaces);
System.Console.WriteLine("Enter any key to close.");
System.Console.ReadKey();
}
}
Вот что я хочу получить:
<Employees>
<Employee>First</Employee>
<Employee>Second</Employee>
<Employee>Third</Employee>
</Employees>
Но я получаю эту ошибку во время выполнения:
System.InvalidOperationException: для типа Person может быть указан только атрибут XmlRoot. Используйте XmlSchemaProviderAttribute, чтобы указать тип схемы.
Примечание Когда мой класс Person не реализует IXmlSerializable
, все работает хорошо...
Может ли кто-нибудь помочь мне в этом?
Выбранное решение (на основе @dbc answer)
Как указал @dbc, использование «суррогатного» класса - это самый простой способ сделать то, что я хочу. Но, как я уже сказал, мне нужно динамически менять тип Person, а это значит, что я не могу использовать теги атрибутов.
Так что я все еще использую XmlAttributeOverrides
в своем окончательном дизайне, вот он:
Суррогатный List<Person>
класс (то же, что и @dbc без тегов атрибутов):
public class EmployeesListSurrogate
{
public List<Person> EmployeeList { get; set; }
public static implicit operator List<Person>(EmployeesListSurrogate surrogate)
{
return surrogate == null ? null : surrogate.EmployeeList;
}
public static implicit operator EmployeesListSurrogate(List<Person> employees)
{
return new EmployeesListSurrogate { EmployeeList = employees };
}
}
Тестовый класс с использованием суррогата:
class Program
{
static void Main(string[] args)
{
List<Person> lPersonList = new List<Person> {
new Person("First"),
new Person("Second"),
new Person("Third")
};
XmlAttributeOverrides lOverrides = new XmlAttributeOverrides();
XmlAttributes lEmployeesListAttributes = new XmlAttributes { XmlRoot = new XmlRootAttribute("Employees") };
lOverrides.Add(typeof(EmployeesListSurrogate), lEmployeesListAttributes);
XmlAttributes lEmployeeAttributes = new XmlAttributes { XmlElements = { new XmlElementAttribute("Employee") } };
lOverrides.Add(typeof(EmployeesListSurrogate), "EmployeeList", lEmployeeAttributes);
XmlSerializer lSerializer = new XmlSerializer(typeof(EmployeesListSurrogate), lOverrides);
XmlSerializerNamespaces lNamespaces = new XmlSerializerNamespaces();
lNamespaces.Add("", "");
lSerializer.Serialize(Console.Out, (EmployeesListSurrogate)lPersonList, lNamespaces);
}
}
Я хочу закончить это с большой благодарностью @dbc, ваш ответ был очень полезным и информативным, я многому научился. Я не могу проголосовать за вас, но я надеюсь, что сообщество сделает это!