понедельник, 21 февраля 2011 г.

Решение на CLinq

Интересная библиотека - Continuous Linq. Позволяет сделать "наблюдаемую" выборку, используя Linq и соответствующие методы-расширения.

Я попробовал решить исходную задачу с помощью следующего кода (правда пришлось заменить самописные ObservableCollection и сопутствующие классы на те что включены в сборку WindowsBase от третьего фреймворка):
var coll = new ContinuousCollection<Page>();

var res = 
 coll.Select(p => new Rectangle(Point.Empty, p.Size))
 .Concat(coll.Select(p => p.PageHeader.Rect))
 .Concat(coll.SelectMany(p => p.Items).Select(block => block.Rect))
 .Concat(coll.SelectMany(p => p.Items).SelectMany(b => b.Items).Select(t => t.Rect))
 ;

NotifyCollectionChangedEventHandler h = (sender, args) =>
 {
  if (args.OldItems != null)
   foreach (var oldItem in args.OldItems)
   {
    invalidateHandler((Rectangle) oldItem);
   }
  if (args.NewItems != null)
   foreach (var newItem in args.NewItems)
   {
    invalidateHandler((Rectangle) newItem);
   }
 };

res.CollectionChanged += h;

coll.Add(page);
return new DisposeDelegate(() => res.CollectionChanged -= h);

Стандартный набор тестов проходит. Несколько тестов падает, но это непринципиально (проблема момента начала наблюдения).

Интересно, совпадают ли мощности у CLinq и моего решения в плане отслеживания изменений, то есть все ли задачи доступные CLinq решаются механизмом подписки. Если это так, то можно сделать билдер на тех же LINQ расширениях. Другая задача - это генерация последовательности, аналогичной CLinq.

Комментариев нет: