Upload
andrew-mayorov
View
719
Download
4
Embed Size (px)
DESCRIPTION
Доклад на SEF-2009
Citation preview
ObjectXPathNavigator – Как и зачем?
Андрей Майоров. BYTE-force
Зачем нужен (ObjectXPathNavigator)?
• Операции над графом объектов в памяти:– Перемещение по дереву. Любой объект в
качестве корня.– Автоматически формируется дерево XML-узлов.– Выборки нужных объектов через XPath.
• Граф объектов – в XSLT.
История
XPath Querying Over Objects with ОbjectXPathNavigator• Статья в MSDN March 2003. Steve Saxon, Dell
Computer Corporation.
JXPath• Простой интерпретатор XPath; может быть
применен к обычным графам объектов.• Позволяет выполнять XPath-запросы и получать
итераторы.
XPathObjectNavigator в Bamboo.Prevalence• Версия Java-библиотека Prevayler для .NET. • Содержит XPathObjectNavigator (аналог JXPath).
Недостатки других решений
• Невозможность управлять формой XML– Что идет в элементы?– А что в атрибуты?– С какими именами?– А неймспейсы какие?
• Не расширяются снаружи– Как конвертировать значение в атрибут?– Специальная обработка нужного класса?
Еще есть XmlSerializer
• Стандартней некуда.• Позволяет управлять формой.
• НО сначала преобразует все в XML, и только потом отдает его приложению.
ObjectXPathNavigator
Использование #1
var context = new ObjectXPathContext();var nav = context.CreateNavigator( o );
var ctx = new ObjectXPathContext( nsmgr );ctx.NamespaceManager.AddNamespace( "sdf", “…” );var nav = ctx.CreateNavigator( o );
Простейшее использование
Регистрация неймспейса
Использование #2
ObjectXPathContext context = new ObjectXPathContext( nsmgr );
context.RegisterNodePolicy( typeof( INullableType ), typeof( NullableNodePolicy ) );
context.ConverterFactory.AddConverter( typeof( NullableDateTime ), new NullableDateTimeConverter() );
XPathNavigator nav = context.CreateNavigator( o );
Регистрация специальной политики и конвертера
Разметка объектов
[XmlRoot( "product", Namespace=Namespaces.SDF )]public class Product{
[XmlAttribute( "id" )]public int ProductId{ get; set; }
[XmlAttribute( "name" )]public string Field1{ get; set; }
[XmlElement( "description" )]public string Description{ get; set ; }
[XmlElement( "Date", Form=XmlSchemaForm.Unqualified )][Converter( typeof( SimpleConverter ))]public DateTime Date{ get; set ; }
[XmlAnyElement]public XmlElement Xml{ get; set; }
}
Разметка атрибутами:
<sdf:productid="123" name="Red button" xmlns:sdf="...">
<sdf:description>Red button description
</sdf:description>
<Date>10.10.2006</Date>...
</sdf:product>
XML:
ObjectXPathNavigator
• Центральный класс библиотеки.• Наследует у класса XPathNavigator.• Осуществляет движение по дереву узлов (элементов, атрибутов).• Дерево динамически создается по мере спуска по иерархии.• Умеет работать с «дочерними» навигаторами.• Узлы дерева хранятся в виде экземпляров класса Node.
Node
• Аналогичен классу XmlNode.• «Отражает» реальный объект или связи между объектами.• Получение реального значения делается, когда это требуется *.
* Есть тонкости.
NodePolicy
• Политика отвечает за поведение узла иерархии.• Соответствует паттерну Policy (Strategy).• Упрощает расширение.• Позволяет менять поведение узлов на ходу.
Стандартные политики
• GenericNodePolicyПреобразует свойства обычного объекта в элементы и атрибуты.
• MemberNodePolicy Обслуживает узлы, значение которых еще не уточнялось навигатором.
• TextNodePolicy Для узлов типа «элемент», относящихся к полям с «простыми» значениями.
• ListNodePolicy Позволяет перемещаться по содержимому объектов, реализующих интерфейс IList.
Конвертеры
• В XML некоторые части графа объектов показаны в виде простого текста.
• Конвертеры преобразуют значения полей в текст.• Можно писать новые конвертеры и регистрировать их
Некоторые стандартные конвертеры• GenericConverter – просто использует ToString().• BooleanConverter, DateTimeConverter, DoubleConverter и т.п. –
форматируют результат в тот формат, который принят для XML.• EnumConverter – преобразует значение в название.
Прозрачные узлы?
public class Person { public string Name; public string[] Alias;
}
<Person><Name>John Smith</Name> <Alias>
<string>Johnny</string> <string>Smithy</string>
</Alias> </Person>
<person> <name>John Smith</name> <alias>Johnny</alias> <alias>Smithy</alias>
</person>
Берем класс … получим XML:
А хотелось-то получить:
Прозрачные узлы!• Прозрачный узел – способ управления формой XML.• Навигатор не останавливается на прозрачном узле• Сделать узел прозрачным:
• Атрибут [Transparent(true)].• Метод INodePolicy.GetIsTransparent().
• Некоторые узлы делаются прозрачными для соответствия правилам класса XmlSerializer*.
* Следуем пока не всем правилам.
Добавление своих политик
• Реализуем интерфейс INodePolicy.• Методы самоочевидны.• В классе нужен метод GetPolicy().
Регистрация политики• Атрибут NodePolicy на свойстве или классе.• Метод RegisterNodePolicy (тип объекта, тип политики).
– Тип объекта может быть интерфейсом.
• Событие NodePolicyGet.
public static new INodePolicy GetPolicy()
INodePolicy
public interface INodePolicy{
INodePolicy GetNewPolicy( Node node );string GetName( Node node );string GetNamespace( Node node );XPathNodeType GetNodeType( Node node );string GetValue( Node node );bool GetIsTransparent( Node node );int GetAttributesCount( Node node );Node GetAttribute( Node node, int index );int FindAttribute( Node node, string name, string ns );int GetChildrenCount( Node node );Node GetChild( Node node, int index );
}
При смене объекта
Свои конвертеры
• Реализует интерфейс IConverter.• ToString - преобразует значение объекта в текст.• ParseString в данной версии не используется.
Регистрация конвертера• Атрибут Converter на свойстве или классе.• Используя метод AddConverter.
public interface IConverter{
string ToString( object obj );object ParseString( string str );
}
Возможные улучшения
• Полная совместимость со стандартным сериализатором.• Оптимизация чтения данных. • Обновление данных через навигатор.• Типизированные элементы и атрибуты.• Предотвращение зацикливания.• и т.д.
Заключение
• Лицензия MIT-style.• Текущая версия на нашем сайте:
http://blogs.byte-force.com/files/12/objectxpathnavigator/default.aspx
• Free as in beer: