Last active
June 20, 2022 15:29
-
-
Save RolandPheasant/3bba5e32f2eefb70c538ce4acabf17cb to your computer and use it in GitHub Desktop.
Extension for a transform with an inline update
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class DynamicDataEx | |
{ | |
/// <summary> | |
/// Transforms the items, and when an update is received, allows the preservation of the previous view model | |
/// </summary> | |
/// <typeparam name="TObject">The type of the object.</typeparam> | |
/// <typeparam name="TKey">The type of the key.</typeparam> | |
/// <typeparam name="TDestination">The type of the destination.</typeparam> | |
/// <param name="source">The source.</param> | |
/// <param name="transformFactory">The transform factory.</param> | |
/// <param name="updateAction">Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem </param> | |
/// <returns></returns> | |
public static IObservable<IChangeSet<TDestination, TKey>> TransformWithInlineUpdate<TObject, TKey, TDestination>(this IObservable<IChangeSet<TObject, TKey>> source, | |
Func<TObject, TDestination> transformFactory, | |
Action<TDestination, TObject> updateAction = null) | |
{ | |
return source.Scan((ChangeAwareCache<TDestination, TKey>)null, (cache, changes) => | |
{ | |
if (cache == null) | |
cache = new ChangeAwareCache<TDestination, TKey>(changes.Count); | |
foreach (var change in changes) | |
{ | |
switch (change.Reason) | |
{ | |
case ChangeReason.Add: | |
cache.AddOrUpdate(transformFactory(change.Current), change.Key); | |
break; | |
case ChangeReason.Update: | |
{ | |
if (updateAction == null) continue; | |
var previous = cache.Lookup(change.Key) | |
.ValueOrThrow(()=> new MissingKeyException($"{change.Key} is not found.")); | |
updateAction(previous, change.Current); | |
//send a refresh as this will force downstream operators | |
cache.Refresh(change.Key); | |
} | |
break; | |
case ChangeReason.Remove: | |
cache.Remove(change.Key); | |
break; | |
case ChangeReason.Refresh: | |
cache.Refresh(change.Key); | |
break; | |
case ChangeReason.Moved: | |
//Do nothing ! | |
break; | |
} | |
} | |
return cache; | |
}).Select(cache => cache.CaptureChanges()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That will be accommodated for when I port the operator into the library.
The existing transform operator by default also does not respond to a refresh but, has a "transformOnRefresh" flag which the user can opt into.
For now, you can simply add an extra line of code to the snippet.
should become
and it will do as you expect