/// <summary> /// Initializes a new instance of the <see cref="InnerJoinReadOnlyObservableCollection{TOuter, TInner, TKey, TResult}"/> class. /// </summary> /// <param name="outerSource">The outer source.</param> /// <param name="innerSource">The inner source.</param> /// <param name="outerKeySelector">The outer key selector.</param> /// <param name="innerKeySelector">The inner key selector.</param> /// <param name="resultSelector">The result selector.</param> /// <param name="keyComparer">The key comparer.</param> /// <param name="outerComparer">The comparer of outer items.</param> /// <param name="innerComparer">The comparer of inner items.</param> /// <exception cref="ArgumentNullException"> /// outerSource /// or /// innerSource /// or /// outerKeySelector /// or /// innerKeySelector /// or /// resultSelector /// </exception> public InnerJoinReadOnlyObservableCollection( IEnumerable <TOuter> outerSource, IEnumerable <TInner> innerSource, Func <TOuter, IObservable <TKey> > outerKeySelector, Func <TInner, IObservable <TKey> > innerKeySelector, Func <TOuter, TInner, IObservable <TResult> > resultSelector, IEqualityComparer <TKey> keyComparer = null, IEqualityComparer <TOuter> outerComparer = null, IEqualityComparer <TInner> innerComparer = null) { _outerSource = outerSource ?? throw new ArgumentNullException(nameof(outerSource)); _innerSource = innerSource ?? throw new ArgumentNullException(nameof(innerSource)); _outerKeySelector = outerKeySelector ?? throw new ArgumentNullException(nameof(outerKeySelector)); _innerKeySelector = innerKeySelector ?? throw new ArgumentNullException(nameof(innerKeySelector)); _resultSelector = resultSelector ?? throw new ArgumentNullException(nameof(resultSelector)); _keyComparer = keyComparer ?? EqualityComparer <TKey> .Default; _innerComparer = new KeyValuePairEqualityComparer <TInner>(innerComparer); _outerComparer = new KeyValuePairEqualityComparer <TOuter>(outerComparer); _outerItems = new ObservableDictionary <TKey, ObservableItemContainer <TOuter, TKey> >( new Dictionary <TKey, ObservableItemContainer <TOuter, TKey> >(_keyComparer)); _innerItems = new ObservableDictionary <TKey, ObservableItemContainer <TInner, TKey> >( new Dictionary <TKey, ObservableItemContainer <TInner, TKey> >(_keyComparer)); _mergedItems = new ObservableDictionary <TKey, ObservableItemContainer <Tuple <TOuter, TInner>, TResult> >( new Dictionary <TKey, ObservableItemContainer <Tuple <TOuter, TInner>, TResult> >(_keyComparer)); foreach (var item in _outerSource) { _outerItems.Add(CreateContainer(item, _outerKeySelector)); } foreach (var item in _innerSource) { _innerItems.Add(CreateContainer(item, _innerKeySelector)); } var merge = _outerItems.Values.Join(_innerItems.Values, outer => outer.Value, inner => inner.Value, Tuple.Create); foreach (var pair in merge) { _mergedItems.Add(pair.Item1.Value, Merge(pair.Item1.Item, pair.Item2.Item)); } _outerItems.CollectionChanged += OuterItemsOnCollectionChanged; _innerItems.CollectionChanged += InnerItemsOnCollectionChanged; _mergedItems.Values.CollectionChanged += MergedItemsOnCollectionChanged; _mergedItems.Values.PropertyChanged += (sender, args) => OnPropertyChanged(args); if (_innerSource is INotifyCollectionChanged innerNotifier) { CollectionChangedEventManager.AddListener(innerNotifier, this); } if (_outerSource is INotifyCollectionChanged outerNotifier) { CollectionChangedEventManager.AddListener(outerNotifier, this); } }
public void GetHashCodeTest() { var testSamples = new Dictionary<String, String> { { "a0", "abc00" }, { "b1", "abc12" }, { "c2", "abc13" }, { "d3", "abc14" } }; var comparer = new KeyValuePairEqualityComparer<String, String>(StringComparer.Ordinal, StringComparer.OrdinalIgnoreCase); foreach (var testSample in testSamples) { { Assert.AreEqual(testSample.GetHashCode(), comparer.GetHashCode(testSample)); } } }