пятница, 27 сентября 2013 г.

Мои предложения в Camlex

Для тех, кто давно работает с Sharepoint, не будет секретом, что такое Camlex.NET. Эта библиотека позволяет строить запросы CAML через fluent-интерфейс.
В одном из наших проектов Camlex активно используется, и я заметил за ним некоторые недочеты. О чем и хотелось бы сегодня рассказать.

Неподдерживаемые операции

Самое первое, что меня неприятно удивило, так это невозможность встроить в результирующий запрос неподдерживаемые библиотекой условия. Список поддерживаемых операций можно найти в документации. Туда, например, не входит Membership.
Однако интерфейс центрального типа в API Camlex вполне позволяет добавлять сторонние условия в виде строки.

public interface IQuery { IQuery Where(Expression<Func<SPListItem, bool>> expr); IQuery WhereAll(IEnumerable<Expression<Func<SPListItem, bool>>> expressions); IQuery WhereAll(string existingWhere, Expression<Func<SPListItem, bool>> expression); IQuery WhereAll(string existingWhere, IEnumerable<Expression<Func<SPListItem, bool>>> expressions); IQuery WhereAll(IEnumerable<string> expressions); IQuery WhereAny(IEnumerable<Expression<Func<SPListItem, bool>>> expressions); IQuery WhereAny(string existingWhere, Expression<Func<SPListItem, bool>> expression); IQuery WhereAny(string existingWhere, IEnumerable<Expression<Func<SPListItem, bool>>> expressions); IQuery WhereAny(IEnumerable<string> expression);
...
}

existingWhere не оправдывают надежды, потому что внутри все они обрабатываются следующим образом:

public IQuery WhereAll(string existingWhere, IEnumerable<Expression<Func<SPListItem, bool>>> expressions) { var where = this.getWhereExpressionFromString(existingWhere); var exprs = new List<Expression<Func<SPListItem, bool>>>(expressions); exprs.Add(where); return this.WhereAll(exprs); }

То есть строка преобразуется в дерево выражений, а самописный транслятор не подразумевает неподдерживаемые операции. Однако технически нет никаких проблем с их поддержкой. Where условие перманентно представлено в типе в виде элемента XML:

internal class Query : IQueryEx {
...
private XElement where;
...
}

Я сделал форк Camlex.NET и добавил возможность внедрять неподдерживаемые операции через existingWhere параметры. Ни один интерфейс типов не пострадал.

Перезапись условий

Второй неожиданностью стало то, что запрос не аккумулировал условия. Например, если задать подряд два условия

Camlex.Query().Where(x => x["Status"] != null).Where(x => x["Title"] == "Hello world!");

то запрос запомнит только последнее условие. Такой поворот событий ставит под сомнение использование оригинального типа запроса Camlex в качестве аккумулятора сложных условий. А очень хотелось бы.
В своем форке я доработал Query тип, чтобы он мог накапливать условия. Естественно, эта новая функциональность не имеет обратной совместимости с оригинальной библиотекой. Поэтому использовать в старых проекта ее надо с осторожностью.
Это будет причиной тому, что скорее всего форк никогда не попадет основную ветку.

1 комментарий:

  1. Правило CSC510224 сделали в SPCAFContrib:
    https://spcafcontrib.codeplex.com/workitem/12242/

    ОтветитьУдалить