Created
March 7, 2018 14:09
-
-
Save MrAntix/5b3cb31b5642c98a30e3327f246309f8 to your computer and use it in GitHub Desktop.
Apply changes to a list with a serializable list of add/updates and removes
This file contains hidden or 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 class Changes<T> | |
{ | |
public Changes( | |
IEnumerable<T> toAddOrUpdate = null, | |
IEnumerable<T> toRemove = null) | |
{ | |
ToAddOrUpdate = toAddOrUpdate?.ToImmutableArray() ?? ImmutableArray<T>.Empty; | |
ToRemove = toRemove?.ToImmutableArray() ?? ImmutableArray<T>.Empty; | |
} | |
public IImmutableList<T> ToAddOrUpdate { get; } | |
public IImmutableList<T> ToRemove { get; } | |
public Changes<T> AddOrUpdate(params T[] items) | |
{ | |
return new Changes<T>( | |
ToAddOrUpdate.Concat(items), | |
ToRemove); | |
} | |
public Changes<T> Remove(params T[] items) | |
{ | |
return new Changes<T>( | |
ToAddOrUpdate, | |
ToRemove.Concat(items)); | |
} | |
} | |
public static class Changes | |
{ | |
public static Changes<T> AddOrUpdate<T>(params T[] items) | |
{ | |
return new Changes<T>(items, null); | |
} | |
public static Changes<T> Remove<T>(params T[] items) | |
{ | |
return new Changes<T>(null, items); | |
} | |
} |
This file contains hidden or 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 ChangesExtensions | |
{ | |
public static IImmutableList<T> Apply<T>( | |
this IEnumerable<T> items, | |
Changes<T> changes, | |
IEqualityComparer<T> comparer = null) | |
{ | |
var result = items.ToList(); | |
if (comparer == null) | |
{ | |
comparer = EqualityComparer<T>.Default; | |
} | |
foreach (var toAddUpdate in changes.ToAddOrUpdate) | |
{ | |
var found = false; | |
for (var i = 0; i < result.Count; i++) | |
if (comparer.Equals(result[i], toAddUpdate)) | |
{ | |
result[i] = toAddUpdate; | |
found = true; | |
break; | |
} | |
if (!found) result.Add(toAddUpdate); | |
} | |
return result.Except(changes.ToRemove).ToImmutableArray(); | |
} | |
} |
This file contains hidden or 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 class ChangesTests | |
{ | |
[Fact] | |
public void adds() | |
{ | |
var a = new[] { Guid.NewGuid(), Guid.NewGuid() }; | |
var toAdd = new[] { Guid.NewGuid() }; | |
var changes = Changes.AddOrUpdate(toAdd); | |
var b = a.Apply(changes); | |
Assert.Equal(a.Concat(toAdd), b); | |
} | |
[Fact] | |
public void remove() | |
{ | |
var a = new[] { Guid.NewGuid(), Guid.NewGuid() }; | |
var toRemove = a.Take(1).ToArray(); | |
var changes = Changes.Remove(toRemove); | |
var b = a.Apply(changes); | |
Assert.Equal(a.Skip(1), b); | |
} | |
[Fact] | |
public void update() | |
{ | |
var a = new[] { new Thing(""), new Thing("") }; | |
var toUpdate = new[] { new Thing(a[0].Key, "Updated") }; | |
var changes = Changes.AddOrUpdate(toUpdate); | |
var b = a.Apply(changes); | |
Assert.Equal(toUpdate[0].Value, b[0].Value); | |
Assert.Same(a[1], b[1]); | |
} | |
public class Thing : IEquatable<Thing> | |
{ | |
public Thing(Guid key, string value) | |
{ | |
Key = key; | |
Value = value; | |
} | |
public Thing(string value) : | |
this(Guid.NewGuid(), value) | |
{ | |
} | |
public Guid Key { get; } | |
public string Value { get; } | |
bool IEquatable<Thing>.Equals(Thing other) | |
{ | |
return Key == other.Key; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment