C #: Использование сборок (через отражение) в качестве (мета) хранилища данных - PullRequest
2 голосов
/ 26 января 2010

НЕКОТОРЫЙ КОНТЕКСТ

  • один из моих проектов требует переноса некоторых "метаданных" (да, я ненавижу использовать это слово).
  • То, из чего конкретно состоят метаданные, не важно, только то, что оно более сложное, чем простая «таблица» или «список» - вы можете думать о нем как о мини-базе данных информации
  • В настоящее время эти метаданные хранятся в файле XML, и у меня есть XSD, определяющий схему.
  • Я хочу упаковать эти метаданные в свой проект, в настоящее время это означает сохранение XML-файла в качестве ресурса
  • Однако я искал более строго типизированную альтернативу . Я подумываю переместить его из XML-файла в код на C #, поэтому вместо использования XML-API для обхода моих метаданных, опираясь на код .NET через отражение типов
  • Помимо строгой (эр) типизации, некоторые полезные характеристики, которые я вижу при использовании сборки, предназначены для этого: (1) я могу в некоторой степени реорганизовать «схему» с помощью таких инструментов, как Resharper, (2) метаданные могут поставляться с код (3) не должен полагаться на какой-либо внешний компонент БД.

ВОПРОСЫ

  • Если вы попробовали что-то подобное, мне любопытно, что вы узнали.
  • Был ли ваш опыт положительным?
  • Что вы узнали?
  • Какие проблемы в этом подходе вы обнаружили?
  • Какие соображения я должен принять во внимание?
  • Вы бы сделали это снова?

ПРИМЕЧАНИЯ

  • Не спрашиваю, как использовать Reflection - там помощь не нужна
  • В основном спрашиваю о вашем опыте и конструктивных соображениях

ОБНОВЛЕНИЕ: ИНФОРМАЦИЯ О МЕТАДАТАХ

Поскольку люди спрашивают, я попытаюсь описать метаданные немного подробнее. Я пытаюсь немного абстрагироваться - так что это покажется немного искусственным.

В модели есть три объекта:

  • Набор "групп" - каждая группа имеет уникальное имя и несколько свойств (обычно значения int, которые представляют собой идентификационные номера некоторого вида)
  • Каждая «группа» содержит 1 или более «виджетов» (не более 50) - каждый элемент имеет такие свойства, как имя (есть несколько имен), идентификаторы и различные логические свойства.
  • Каждый виджет содержит один или несколько «сценариев». Каждый «сценарий» - это документация - URL-адрес описания использования виджета.

Обычно мне нужно выполнить такие "запросы"

  • Получить имена всех виджетов
  • Получить имена всех групп, которые содержат хотя бы один виджет, где BoolProp1 = true
  • Получить идентификатор виджета, в группу которого входит этот виджет

Как я думал о моделировании сущностей в сборке

  • Есть 3 класса: группа, виджет, документация
  • Есть 25 групп, поэтому у меня будет 25 групповых классов - поэтому "FooGroup" будет производным от группы, тот же шаблон следует для виджетов и документации
  • Каждый класс будет иметь атрибуты для учета имен, идентификаторов и т. Д.

Ответы [ 2 ]

1 голос
/ 26 января 2010

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

(Основные категории широко используемых атрибутов включают O / R Mappers, инфраструктуру внедрения зависимостей и описание сериализации - особенно XML-сериализация)

Хорошо, я попрошу вас немного подробнее рассказать о природе данных, которые вы хотите встроить в качестве ресурса. Использование атрибутов, естественно, хорошо для типа данных, которые описывают ваши типы и элементы типов, но каждое использование атрибутов является простым и коротким. Атрибуты (я думаю) должны быть очень связными и как-то независимыми друг от друга.

Одним из решений, на которое я хочу вам указать, является подход «Сериализация XML». Вы можете сохранить свои текущие XML-файлы и поместить их в свои сборки как Embedded Resource (что вы, вероятно, уже сделали) и сразу прочитать весь XML-код в строго типизированную иерархию объектов.

Сериализация XML очень проста в использовании, на мой взгляд, намного проще, чем типичный XML API или даже LINQ2XML. Он использует атрибуты для сопоставления свойств класса с элементами XML и атрибутами XML. После того, как вы загрузили XML в объекты, у вас в памяти есть все, что вы хотите, в виде «типизированных» данных.

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

У меня много положительного опыта использования XML-сериализации для большого количества данных. Вы можете упорядочивать данные по своему усмотрению, вы получаете безопасность типов, вы получаете IntelliSence (если вы отдаете XSD визуальной студии), а также вы получаете половину Рефакторинга. ReSharper (или любой другой известный мне инструмент рефакторинга) не распознает сериализацию XML, поэтому, когда вы реорганизуете типизированные классы, он не меняет сам XML, а меняет все использование данных.

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

Для примеров сериализации XML, просто Google "Сериализация XML" или посмотрите его в MSDN.

UPDATE

Я настоятельно рекомендую НЕ использовать классы для представления экземпляров ваших данных. Или даже использование класса для инкапсуляции данных противоречит их логическому определению.

Полагаю, лучшим вариантом будет сериализация XML при условии, что у вас уже есть данные в формате XML. Вы получаете все преимущества, которые хотите, с меньшим количеством кода. И вы можете выполнить любой запрос к сериализуемым объектам XML, используя LINQ2Objects.

Часть вашего кода может выглядеть следующим образом:

[XmlRoot]
public class MyMetadata
{

    [XmlElement]
    public Group[] Groups { get; set; }

}

public class Group
{

    [XmlAttribute]
    public string Name { get; set; }

    [XmlAttribute]
    public int SomeNumber { get; set; }

    [XmlElement]
    public Widget[] Widgets { get; set; }

}

public class Widget
{
    ...
}

Вы должны вызвать new XmlSerializer(typeof(MyMetadata)), чтобы создать сериализатор, и вызвать его Deserialize метод, передав ему поток вашего XML, и вы получите заполненный экземпляр класса MyMetadata.

1 голос
/ 26 января 2010

Из вашего описания непонятно, но похоже, что у вас есть метаданные уровня сборки, к которым вы хотите иметь доступ (в отличие от уровня типа). Вы можете иметь один класс в каждой сборке, который реализует общий интерфейс, а затем использовать отражение, чтобы выследить этот класс и создать его экземпляр. Затем вы можете жестко закодировать метаданные внутри.

Конечно, проблемы заключаются в преимуществах, которые вы теряете из XML, а именно в том, что вы не можете изменять метаданные без новой сборки. Но если вы идете в этом направлении, вы, вероятно, уже приняли это во внимание.

...