Как улучшить интерфейсную сериализацию на основе интерфейса? - PullRequest
1 голос
/ 22 января 2011

Я разрабатываю управляемую интерфейсом инфраструктуру сериализации для использования с интерфейсами для сериализации данных XML.

Конечная цель состоит в том, чтобы эта структура могла сохранять / загружать состояние объекта (или его части, видимой призмы интерфейса мысли), используя интерфейсы в качестве абстракции.

Размышляя о дизайне, я обнаружил, что используя атрибуты C #, я могу предоставить инфраструктуру с необходимой информацией для сохранить и загрузить состояние объекта, а также способ, как выполнить сериализацию / десериализацию. В качестве преимущества я обнаружил, что не существует решения, способного к частичному сохранению / восстановлению объекта. Если я опишу данные XML в терминах интерфейса с атрибутами данных, я обнаружу, что больше не требуется иметь зависимость от этого интерфейса из класса (так что классу больше не требуется реализовывать данный интерфейс для XML данные).

У меня есть вопрос об использовании класса XmlObjectSerializer из-за некоторых проблем с юзабилити. Вот пример объявления интерфейса, который тестируется:

Вот учебник для начинающих:

    interface IPersonRoot
    {
        string Name { get; set; }
    }

    [XmlRootSerializer("Body")]
    interface IPersonCustomRoot
    {
        string Name { get; set; }
    }

    interface IPersonAttribute
    {
        [XmlAttributeRuntimeSerializer]
        string Name { get; set; }
    }

    interface IPersonCustomAttribute
    {
        [XmlAttributeRuntimeSerializer("Id")]
        string Name { get; set; }
    }

    interface IPersonElement
    {
        [XmlElementRuntimeSerializer]
        string Name { get; set; }
    }

    interface IPersonCustomElement
    {
        [XmlElementRuntimeSerializer("Head")]
        string Name { get; set; }
    }

    interface IPersonCustomElementString
    {
        [XmlElementRuntimeSerializer("Head", typeof(string))]
        string Name { get; set; }
    }

    interface IVeryImportantPersonRoot : IPersonRoot
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomRoot : IPersonCustomRoot
    {
        Guid Id { get; set; }
    }

    [XmlRootSerializer("Spirit")]
    interface IVeryImportantPersonCustomRootOverride : IPersonCustomRoot
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonAttribute : IPersonAttribute
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomAttribute : IPersonCustomAttribute
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonElement : IPersonElement
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomElement : IPersonCustomElement
    {
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomElementOverride : IPersonCustomElement
    {
        [XmlElementRuntimeSerializer("Guid")]
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomElementOverrideGuid : IPersonCustomElement
    {
        [XmlElementRuntimeSerializer("Guid", typeof(Guid))]
        Guid Id { get; set; }
    }

    interface IVeryImportantPersonCustomRuntimeSerializer : IPersonCustomElement
    {
        Guid Id { get; set; }

        [XmlColorRuntimeSerializer]
        Color Color { get; set; }  
    }

    interface IVeryImportantPersonColor
    {
        string Name { get; set; }

        Guid Id { get; set; }

        [XmlColorRuntimeSerializer]
        Color Color { get; set; }
    }

Вот определение класса XmlObjectSerializer:

public class XmlObjectSerializer
{
        //...
        public static void Load<T>(string xml, Type type, object value)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
            {
                XDocument root = XDocument.Load(XmlReader.Create(ms));
                string rootName = GetRootName(typeof(T), root.Root.Name.ToString());
                IXmlObjectSerializer serializer = Load(root.Root, CreateInternal(null, rootName));
                serializer.Deserialize(type, value);
            }
        }
        public static void Load<T>(string xml, object value)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
            {
                XDocument root = XDocument.Load(XmlReader.Create(ms));
                string rootName = GetRootName(typeof(T), root.Root.Name.ToString());
                IXmlObjectSerializer serializer = Load(root.Root, CreateInternal(null, rootName));
                serializer.Deserialize(typeof(T), value);
            }
        }
        public static string Save<T>(Type type, object value)
        {
            string rootName = GetRootName(typeof(T), value.GetType().Name);
            XmlObjectSerializer result = CreateInternal(null, rootName);
            IXmlRuntimeSerializer serializer = result;
            serializer.Serialize(type, value);
            XDocument root = new XDocument();
            return result.ToXmlString();
        }
        public static string Save<T>(object value)
        {
            string rootName = GetRootName(typeof(T), value.GetType().Name);
            XmlObjectSerializer result = CreateInternal(null, rootName);
            IXmlRuntimeSerializer serializer = result;
            serializer.Serialize(typeof(T), value);
            return result.ToXmlString();
        }
        public static void Load(Stream data, Type type, object value)
        {
            XDocument document = XDocument.Load(XmlReader.Create(data));
            string rootName = GetRootName(type, document.Root.Name.ToString());
            IXmlObjectSerializer serializer = Load(document.Root, CreateInternal(null, rootName));
            serializer.Deserialize(type, value);
        }
        public static void Save(Stream data, Type type, object value)
        {
            string rootName = GetRootName(type, value.GetType().Name);
            XmlObjectSerializer serializer = CreateInternal(null, rootName);
            serializer.Save(type, data, value);
        }
}

Тогда возникает вопрос:

Лучше ли изменить класс XmlObjectSerializer, чтобы он был более универсальным, например XmlObjectSerializer, или просто скрыть все открытые методы, которые используют тип в качестве аргумента? У меня есть предупреждение статического анализатора компилятора, в котором говорится, что использование универсальных методов (т.е. Load (...), Save (...)) в неуниверсальном классе является плохой практикой и должно быть заменено на метод, принимающий Введите в качестве аргумента.

Проблема в том, должен ли я изменить дизайн класса XmlObjectSerializer, следуя этому правилу (в этом случае я потеряю общий подход), и использовать объект и тип в качестве аргументов или оставить методы нетронутыми.

Можете ли вы дать мне совет, а также примеры кода, связанные с размещенным примером кода?

Phanx

1 Ответ

2 голосов
/ 22 января 2011

Я думаю, что конкретное предупреждение компилятора в общем случае является мусором;Вы всегда должны смотреть на конкретный случай.

Написав несколько таких платформ, я бы согласился, что важно включить API на основе Type, поскольку существует множество сценариев для таких библиотек, в которых универсальныенеприятность.Оптимизируя неуниверсальный случай (вместо использования MakeGenericMethod), вы можете сделать другое очень просто:

Foo(Type type, ...) {...}
Foo<T>(...) { Foo(typeof(T), ...); }

Это происходит от того, что кто-то сейчас переписывает библиотеку, чтобы переместить оптимизированный случай в Type вместо<T>.Это , особенно , важно для компактной среды и т. Д., Где в противном случае вы можете начать получать исключения отсутствующего метода, когда ему не хватает места.

Re интерфейсы;выглядит грязно и сложно - tl; dr;на что.Но пока ты счастлив ...

...