Универсальный метод десериализации XML
У меня есть следующий XML файл:
<Root>
<Document>
<Id>d639a54f-baca-11e1-8067-001fd09b1dfd</Id>
<Balance>-24145</Balance>
</Document>
<Document>
<Id>e3b3b4cd-bb8e-11e1-8067-001fd09b1dfd</Id>
<Balance>0.28</Balance>
</Document>
</Root>
Я десериализую его в этот класс:
[XmlRoot("Root", IsNullable = false)]
public class DocBalanceCollection
{
[XmlElement("Document")]
public List<DocBalanceItem> DocsBalanceItems = new List<DocBalanceItem>();
}
где DocBalanceItem
:
public class DocBalanceItem
{
[XmlElement("Id")]
public Guid DocId { get; set; }
[XmlElement("Balance")]
public decimal? BalanceAmount { get; set; }
}
Вот мой метод десериализации:
public DocBalanceCollection DeserializeDocBalances(string filePath)
{
var docBalanceCollection = new DocBalanceCollection();
if (File.Exists(filePath))
{
var serializer = new XmlSerializer(docBalanceCollection.GetType());
TextReader reader = new StreamReader(filePath);
docBalanceCollection = (DocBalanceCollection)serializer.Deserialize(reader);
reader.Close();
}
return docBalanceCollection;
}
Все работает отлично, но у меня много XML файлов. Помимо написания классов Item
, я должен писать классы ItemCollection
для каждого из них. А также я должен реализовать метод DeserializeItems
для каждого.
Можно ли десериализовать мои XML файлы без создания классов ItemCollection
? Могу ли я написать один общий метод для десериализации всех из них?
Единственное решение, которое приходит на ум - создать интерфейс для всех этих классов. Любые идеи?
Ответы
Ответ 1
Вы можете десериализовать общий List<T>
с помощью XmlSerializer. Однако сначала вам нужно добавить атрибут XmlType
к вашему DocBalanceItem
, чтобы он знал, как названы элементы списка.
[XmlType("Document")]
public class DocBalanceItem
{
[XmlElement("Id")]
public Guid DocId { get; set; }
[XmlElement("Balance")]
public decimal? BalanceAmount { get; set; }
}
Затем измените метод DeserializeDocBalances()
, чтобы вернуть List<T>
, и передайте экземпляр serial , чтобы он попросил его искать Root
в качестве корневого элемента:
public List<T> DeserializeList<T>(string filePath)
{
var itemList = new List<T>();
if (File.Exists(filePath))
{
var serializer = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("Root"));
TextReader reader = new StreamReader(filePath);
itemList = (List<T>)serializer.Deserialize(reader);
reader.Close();
}
return itemList;
}
Затем вы должны иметь возможность делать
var list = DeserializeList<DocBalanceItem>("somefile.xml");
Так как метод теперь возвращает общий List<T>
, вам больше не нужно создавать собственные коллекции для каждого типа.
P.S. - Я тестировал это решение локально с предоставленным документом, он работает.
Ответ 2
Любой строковый объект можно десериализовать следующим методом.
public static T genericDeserializeSingleObjFromXML<T>(T value, string XmalfileStorageFullPath)
{
T Tvalue = default(T);
try
{
XmlSerializer deserializer = new XmlSerializer(typeof(T));
TextReader textReader = new StreamReader(XmalfileStorageFullPath);
Tvalue = (T)deserializer.Deserialize(textReader);
textReader.Close();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("serialization Error : " + ex.Message);
}
return Tvalue;
}
Чтобы использовать этот метод, вы уже должны сериализовать объект в XML файле.
Метод вызова:
XmlSerialization.genericDeserializeSingleObjFromXML(new ObjectName(), "full path of the XML file");