Способ сочетания сериализации с грамматическим разбором? - PullRequest
4 голосов
/ 03 февраля 2011

Я столкнулся с дилеммой. Мое приложение C # использует пользовательский формат файла, который должен быть редактируемым человеком в текстовом редакторе, но также может быть редактируемым через графический интерфейс в моем приложении. Этот файл будет представлять объект верхнего уровня (назовите его TopObject), который содержит несколько более мелких объектов, которые, в свою очередь, содержат другие объекты и т. Д. Все данные, содержащиеся в этих объектах, содержатся в файле.

Я застрял, как решить проблему загрузки / сохранения этих файлов. Сериализация C # не работает для меня, так как она нарушает возможности редактирования человеком (двоичная сериализация) или имеет «проблемы» с сериализацией коллекций базовых классов (сериализация XML и DataContract, которые добавляют текст для устранения неоднозначности производных классов при сериализации базового класса, который делает файлы более хрупкими для редактирования человеком); если бы не было необходимости редактировать файлы вручную, это был бы билет. Я искал генераторы синтаксического анализатора, такие как GOLD и GPLEX / GPPG, чтобы проанализировать и преобразовать файл в объекты, которые они представляют, и это выглядит многообещающе, но это охватывает только одно направление загрузки файлов, не гарантируя, что они сохранены в правильный формат при их записи.

Что было бы замечательно, так это способ указать грамматику, которая обрабатывает оба:
1) Чтение файла с указанной структурой и преобразование его в TopObject и все содержащиеся в нем объекты, а также
2) Получив TopObject, записываем его состояние в файл с такой же структурой.
В значительной степени, единственная грамматика, которая обеспечивает структуру импорта, а также структуру вывода.

Существуют ли такие инструменты или структуры, которые могли бы мне помочь? Это что-то выполнимое, или я слишком серьезно обдумываю, и есть более легкий путь?

Ответы [ 2 ]

4 голосов
/ 03 февраля 2011

Я бы все еще использовал XML, но просто написал свой собственный сериализатор.Вы можете использовать классы чтения / записи XML в .Net для создания простого формата XML:

<TopObject>
    <SubObject>
        <SubObject>
            etc.
        </SubObject>  
        <SubObject>
            etc.
        </SubObject>
    </SubObject>
    <SubObject></SubObject>
</TopObject>

Я не знаю, считаете ли вы это достаточно читабельным для человека, но лучше, чем материал.Сетевой сериализатор создает.Было бы достаточно просто читать / писать рекурсивно.

Пример:

Вот упрощенный пример, который вы можете адаптировать.Предположим, у меня есть этот класс:

public class Node {
    public Node(String _SomeProperty) {
        this.SomeProperty = _SomeProperty;
    }

    public String SomeProperty;

    public List<Node> Children = new List<Node>();
}

Каждый Node имеет свойство, называемое SomeProperty.Это может также иметь детей;подробнее Nodes в собственности Children.

Вот main из консольного приложения, которое создает некоторые данные из этого класса для сериализации:

static void Main(string[] args) {
    // Make some data for testing
    Node baseObject = new Node("This is the base class");

    List<Node> Children = new List<Node>(){
        new Node("This is a child"),
        new Node("This is another child")
    };

    baseObject.Children = Children;

    Node aSubChild = new Node("This is a child of a child");
    baseObject.Children[0].Children = new List<Node>() { aSubChild };

    // Serialize

    XmlWriter writer = XmlWriter.Create("test.xml");

    writer.WriteStartDocument();


    RecursivelySerialize(ref writer, baseObject);
    writer.Flush();
}

Вызывает метод с именем RecursivelySerialize, который выполняет эту реальную работу:

private static void RecursivelySerialize(ref XmlWriter writer, Node sc) {
    writer.WriteStartElement("Node");

    writer.WriteElementString("SomeProperty", sc.SomeProperty);

    if (sc.Children.Count > 0) {
        writer.WriteStartElement("Nodes");

        foreach (Node scChild in sc.Children)
            RecursivelySerialize(ref writer, scChild);

        writer.WriteEndElement();
    }

    writer.WriteEndElement();
}

Этот метод не сложен.Чтобы улучшить его, вы можете использовать Reflection для динамической сериализации любого типа класса.Вот вывод, который я получил (красиво отформатированный) при выполнении кода выше:

<?xml version="1.0" encoding="utf-8"?>
<Node>
    <SomeProperty>This is the base class</SomeProperty>
    <Nodes>
        <Node>
            <SomeProperty>This is a child</SomeProperty>
                <Nodes>
                    <Node>
                        <SomeProperty>This is a child of a child</SomeProperty>
                    </Node>
                </Nodes>
        </Node>
        <Node>
            <SomeProperty>This is another child</SomeProperty>
        </Node>
    </Nodes>
</Node>
1 голос
/ 04 февраля 2011

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

XML / JSON / INI все еще трудно для некоторых технических специалистов, чтобы не испортить (удивительно), но по крайней мере они знакомы некоторым техническим специалистам. Я думаю, что это лучший выбор, чем бросать собственную грамматику. Еще лучше, если вы хотите сделать редактирование файла более удобным для пользователя, вы можете отменить требование «редактируемое человеком» и сделать его таким, чтобы оно могло редактироваться только приложением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...