public interface IMerge<out T>
{
IEnumerable<IMergeMatched<T>> Matched();
IEnumerable<IMergeMatched<T>> Matched(Func<T, T, bool> predicate);
IEnumerable<T> NotMatchedBySource();
IEnumerable<T> NotMatchedBySource(Func<T, bool> predicate);
IEnumerable<T> NotMatchedByTarget();
IEnumerable<T> NotMatchedByTarget(Func<T, bool> predicate);
}
public interface IMergeMatched<out T>
{
T Source { get; }
T Target { get; }
}
public static class Enumerable
{
public static IMerge<TSource> Merge<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> target,
Func<TSource, TSource, bool> predicate)
{
return new Merge<TSource>(source, target, predicate);
}
}
public class Merge<T> : IMerge<T>
{
private readonly Func<T, T, bool> _predicate;
private readonly IEnumerable<T> _source;
private readonly IEnumerable<T> _target;
private IEnumerable<IMergeMatched<T>> _matcheds;
private IEnumerable<T> _notMatchedBySource;
private IEnumerable<T> _notMatchedByTarget;
public Merge(IEnumerable<T> source, IEnumerable<T> taget, Func<T, T, bool> predicate)
{
_source = source;
_target = taget;
_predicate = predicate;
}
public IEnumerable<IMergeMatched<T>> Matched()
{
if (_matcheds == null)
{
Analize();
}
return _matcheds;
}
public IEnumerable<IMergeMatched<T>> Matched(Func<T, T, bool> predicate)
{
return Matched()
.Where(t => predicate.Invoke(t.Source, t.Target))
.ToArray();
}
public IEnumerable<T> NotMatchedBySource()
{
if (_notMatchedBySource == null)
{
Analize();
}
return _notMatchedBySource;
}
public IEnumerable<T> NotMatchedBySource(Func<T, bool> predicate)
{
return NotMatchedBySource()
.Where(predicate)
.ToArray();
}
public IEnumerable<T> NotMatchedByTarget()
{
if (_notMatchedByTarget == null)
{
Analize();
}
return _notMatchedByTarget;
}
public IEnumerable<T> NotMatchedByTarget(Func<T, bool> predicate)
{
return NotMatchedByTarget()
.Where(predicate)
.ToArray();
}
private void Analize()
{
var macheds = new List<MergeMached<T>>();
var notMachedBySource = new List<T>(_source);
var notMachedByTarget = new List<T>(_target);
foreach (var source in _source)
{
foreach (var target in _target)
{
var macth = _predicate.Invoke(source, target);
if (!macth) continue;
macheds.Add(new MergeMached<T>(source, target));
notMachedBySource.Remove(source);
notMachedByTarget.Remove(target);
}
}
_matcheds = macheds.ToArray();
_notMatchedBySource = notMachedBySource.ToArray();
_notMatchedByTarget = notMachedByTarget.ToArray();
}
}
public class MergeMached<T> : IMergeMatched<T>
{
public MergeMached(T source, T target)
{
Source = source;
Target = target;
}
public T Source { get; private set; }
public T Target { get; private set; }
}
如何使用?
var source = new List<MediaFolder>
{
new MediaFolder
{
Id = "Id1",
Name = "Name1",
Path = "Path1"
},
new MediaFolder
{
Id = "Id2",
Name = "Name2",
Path = "Path2"
},
new MediaFolder
{
Id = "Id3",
Name = "Name3",
Path = "Path3"
},
new MediaFolder
{
Id = "Id4",
Name = "Name4",
Path = "Path4"
},
new MediaFolder
{
Id = "Id5",
Name = "Name5",
Path = "Path5"
},
new MediaFolder
{
Id = "Id6",
Name = "Name6",
Path = "Path6"
}
};
var target = new List<MediaFolder>
{
new MediaFolder
{
Id = "Id1",
Name = "Actualizado en el objeto",
Path = "Path1"
},
new MediaFolder
{
Id = "Id3",
Name = "Name3",
Path = "Actualizado tambien"
},
new MediaFolder
{
Id = "Id4",
Name = "Name4",
Path = "Path4"
},
new MediaFolder
{
Id = "Id5",
Name = "Name5",
Path = "Path5"
},
new MediaFolder
{
Id = "Id6",
Name = "Name6",
Path = "Path6"
},
new MediaFolder
{
Id = "Id7",
Name = "Nuevo Item 7",
Path = "Nuevo Item 7"
}
};
var merge = source.Merge(target, (x, y) => x.Id == y.Id);
var toUpdate = merge.Matched((x, y) => x.Name != y.Name | x.Path != y.Path)
.ToArray();
var toDelete = merge.NotMatchedBySource();
var toInsert = merge.NotMatchedByTarget();
Assert.AreEqual(2, toUpdate.Count());
Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id1" & x.Target.Id == "Id1") > 0);
Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id3" & x.Target.Id == "Id3") > 0);
Assert.AreEqual("Id7", toInsert.First().Id);
Assert.AreEqual("Id2", toDelete.First().Id);