Обход произвольного графа объекта C # с использованием XPath / применение XSL-преобразований - PullRequest
10 голосов
/ 16 декабря 2008

Я искал компонент, который позволил бы мне передать произвольный объект C # в преобразование XSL.

Наивный способ сделать это - сериализовать граф объектов, используя XmlSerializer; однако, если у вас большой граф объектов, это может вызвать проблемы с точки зрения производительности. Такие вопросы, как циклические ссылки, ленивая загрузка, прокси и т. Д., Могут еще больше запутать воду.

Лучший подход - иметь некоторый класс Adapter, который реализует IXPathNavigable и XPathNavigator. Одним из таких примеров, с которыми я столкнулся, является ObjectXPathNavigator от Byte-Force - однако большая часть его ключевой документации написана на русском языке, и мои первоначальные тесты, похоже, указывают на то, что он имеет несколько причуд и особенностей.

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

Ответы [ 4 ]

6 голосов
/ 14 ноября 2009

Существует (очень) старая статья MSDN под названием Запрос XPath к объектам с помощью ObjectXPathNavigator , которая реализует аналогичный класс (также называемый ObjectXPathNavigator, что довольно интересно). Я использовал это давным-давно, чтобы запросить некоторые данные из Visual SourceSafe и создать RSS-канал из журнала изменений, и он работал довольно хорошо. Тем не менее, я не делал XSLT с ним, поэтому я не уверен, работает ли это или нет. Также обратите внимание, что он был написан для Framework 1.0, поэтому вам может потребоваться обновить его для более поздних фреймворков. Кроме того, сейчас могут быть более эффективные способы сделать это, но это даст вам отправную точку (и статья хорошо объясняет, как это работает).

2 голосов
/ 11 января 2009

Звучит так, как будто проблема, которую вы пытаетесь решить, довольно интересна.

На первый взгляд, я бы предложил написать собственную реализацию потомка XPathNavigator - есть только 20 с лишним методов для написания, и ни один из них не имеет особенно трудной подписи.

Наивная реализация, использующая не кэшированное отражение, будет медленной (ish), но будет работать как подтверждение концепции, и вы можете внести изменения, чтобы улучшить производительность, если / когда это станет проблемой.

Однако ...

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

Файл XML (по своей природе) представляет собой простую иерархию элементов и атрибутов - в графе узлов нет циклов (или циклов).

Выражение XPath может включать в себя оператор "//", что в широком смысле означает поиск на неограниченной глубине. (Точное определение см. В разделе 2.5 XPath 1.0 .)

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

Вы можете обойти эту проблему, отслеживая родительские узлы в вашем XPathNavigator и создавая исключение, если обнаружен цикл, но я не уверен, насколько это будет жизнеспособным.

0 голосов
/ 15 февраля 2013

Вы можете попробовать что-то вроде этого:

http://code.google.com/p/antix-software/wiki/AntixReflectionQuery

0 голосов
/ 21 января 2009

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

Более конкретно, сделайте каждый узел (объект) элементом с уникальным идентификатором (возможно, предоставленным методом C # GetHashCode ()?). Ссылки на другие объекты (векторы) будут обрабатываться путем ссылки на идентификатор объекта.

Примеры классов (обратите внимание, что я не знаю C #, поэтому мой синтаксис может быть немного не таким):

public class SomeType {
   public int myInt  { get; set; }
}

public class AnotherType {
   public string myString { get; set; }
   public SomeType mySomeType { get; set; }
}

public class LastType {
   public SomeType mySomeType { get; set; }
   public AnotherType myAnotherType { get; set; }
}

public class UserTypes{
    static void Main()
    {
        LastType lt = new LastType();
        SomeType st = new SomeType();
        AnotherType atype = new AnotherType();

        st.myInt = 7;
        atype.myString = "BOB";
        atype.mySomeType = st;
        lt.mySomeType = st;
        lt.myAnotherType = atype;

        string xmlOutput = YourAwesomeFunction(lt);
    }
}

Тогда мы ожидаем, что значение xmlOutput будет примерно таким (обратите внимание, что выбранные значения идентификаторов полностью синтетические):

<ObjectMap>
 <LastType id="0">
   <mySomeType idref="1" />
   <myAnotherType idref="2" />
 </LastType>

 <SomeType id="1">
  <myInt>7</myInt>
 </SomeType>

 <AnotherType id="2">
  <myString>BOB</myString>
  <mySomeType idref="1" />
 </AnotherType>
</ObjectMap>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...