Подтвердить что ты не робот

Универсальный метод десериализации 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? Могу ли я написать один общий метод для десериализации всех из них?

Единственное решение, которое приходит на ум - создать интерфейс для всех этих классов. Любые идеи?

4b9b3361

Ответ 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");