Как сериализовать ICollection<T> как список<T> в Xml?

Я пытаюсь динамически сериализовать список в XML. Я могу это сделать, пока у меня нет ICollection как свойства T.

Я хотел бы динамически перезаписать тип ICollection в List, прежде чем записать его в Xml.

Это то, что я до сих пор.

List<-XmlElementAttribute-> attrToConvertList = new List<-XmlElementAttribute->();

foreach (var propertyInfo in typeof(T).GetProperties())
{
    if (propertyInfo.PropertyType.Name == "ICollection`1")
    {
        XmlElementAttribute attrToConvert = new XmlElementAttribute();
        attrToConvert.ElementName = propertyInfo.Name;
        attrToConvert.Type = typeof(List<>);
        attrToConvert.Type = attrToConvert.Type.MakeGenericType(propertyInfo.PropertyType.GetGenericArguments()[0]);
        attrToConvertList.Add(attrToConvert);
    }
}
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attributesToConvert = new XmlAttributes();

foreach (var xmlElementAttribute in attrToConvertList)
    attributesToConvert.XmlElements.Add(xmlElementAttribute);

overrides.Add(typeof(T), attributesToConvert);
XmlSerializer serializer = new XmlSerializer(typeof(List<T>), overrides);

Я получаю сообщение об ошибке, что не могу сериализовать тип ICollection, потому что это интерфейс. У меня сложилось впечатление, что то, что я делал с XmlAttributeOverrides, должно было перезаписать ICollection в тип List.

2 ответа

Я решил свою первоначальную проблему с помощью Newton.Json для сериализации объекта.

Сериализация XML не обрабатывает интерфейсы, и, очевидно, XmlAttributeOverride не позволяет вам обойти это поведение. Вы можете изменить тип вашего свойства или создать тип только для сериализации, если это свойство List<T>,

Пример:

class RealClass
{
    ICollection<int> SomeInts { get; set; }
}

class MySerializationClass
{
    private readonly RealClass _wrappedObject;
    public SerializationClass() : this(new RealClass()) { }
    public SerializationClass(RealClass wrappedObject)
    {
        _wrappedObject = wrappedObject;
    }
    public List<T> SomeInts
    {
        get { return new List<T>(_wrappedObject.SomeInts); }
        set { _wrappedObject.SomeInts = value; }
    }
}

Вы также можете сделать это с явной реализацией члена интерфейса и использовать интерфейс в большей части вашего кода:

interface IHaveSomeInts
{
    ICollection<int> SomeInts { get; set; }
}

class TheClass : IHaveSomeInts
{
    public List<T> SomeInts { get; set; }
    ICollection<T> IHaveSomeInts.SomeInts
    {
        get { return SomeInts; }
        set { SomeInts = new List<T>(value); }
    }
}

При назначении ICollection<T> для IList<T>Я бы наверное использовал as чтобы увидеть, могу ли я просто привести объект вместо создания нового, чтобы избежать ненужного создания списков.

Другие вопросы по тегам