RolandPheasant / DynamicData.Snippets

'101 samples' of dynamic data and rx in action
139 stars 13 forks source link

Working with 2 dependent ObservableCaches #2

Open crosscourt opened 6 years ago

crosscourt commented 6 years ago

Scenario: Tagging Items 2 caches: SourceCache, SourceCache When item changes, it needs to go thru the list of tags to determine which one applies to it. Similarly, when tag changes, retagging needs to occur.

First not so reactive attempt:

var disposable = tagsCache.Connect().Flatten().Subscribe(change => { Tag tag = change.Current;

_itemCache.Edit(u => {
    if (change.Reason == ChangeReason.Remove)
    {
        foreach (Item item in _itemCache.Items.Where(b => b.Tags.Contains(tag)))
        {
            item.Tags.Remove(tag);
            u.AddOrUpdate(item);
        }
    }
    else
    {
        foreach (Item item in _itemCache.Items)
        {
            Tag existingTag = item.Tags.FirstOrDefault(t => t.Id == tag.Id);
            if (existingTag != null)
            {
                item.Tags.Remove(existingTag);
                u.AddOrUpdate(item);
            }

            bool applies = tag.Applies(item);
            if (applies)
            {
                item.Tags.Add(tag);
                u.AddOrUpdate(item);
            }
        }
    }
});

});

var disposable2 = _itemCache.Connect().WhereReasonsAre(ChangeReason.Add, ChangeReason.Update).Flatten().Subscribe(change => { Item item = change.Current;

instance.Tags.Connect().Flatten().Select(i => i.Current).Subscribe(tag =>
{
    if (!item.Tags.Contains(tag) && tag.Applies(item))
    {
        item.Tags.Add(tag);
    }
});

});

modplug commented 6 years ago

From what I can understand you have a source collection with all the items and you want to filter the items into two separate caches?

In that case you can try something like this:

var sourceCacheA = tagSourceCache
                .Connect()
                .Filter(p => p.Title == "tagA")
                .AsObservableCache();

var sourceCacheB = tagSourceCache
                .Connect()
                .Filter(p => p.Title == "tagB")
                .AsObservableCache();
crosscourt commented 6 years ago

sorry for my poor description. I have 2 separate caches (Items, Tags).

  1. When an item is added/changed/deleted from cache Items, i need to see which Tag will apply to it.
  2. When a Tag is added/changed/deleted, i need to tag the items that are applicable or remove an existing tag from the Items if it no longer applies.

Each tag has a condition, like "Item.Quantity > 10". So any changes to the Item or Tag Condition will need re-evaluation of everything.

RolandPheasant commented 6 years ago

Maybe the ForEachChange() operator can come to the rescue