public ActiveListJoiner(ActiveListJoinBehaviour joinBehaviour, Func <JoinOption <TLeft>, JoinOption <TRight>, TResult> resultSelector, IEnumerable <string> leftResultSelectorPropertiesToWatch, IEnumerable <string> rightResultSelectorPropertiesToWatch)
        {
            _joinBehaviour = joinBehaviour;

            _resultSelector = resultSelector;

            _left        = ActiveValue.Create <TLeft>();
            _leftWatcher = new ValueWatcher <TLeft>(_left, leftResultSelectorPropertiesToWatch);
            _leftWatcher.ValuePropertyChanged += () => OnLeftChanged();

            _rightCollectionWrappper = new CollectionWrapper <TRight>(null, rightResultSelectorPropertiesToWatch?.ToArray());
            _rightCollectionWrappper.ItemModified += (s, i, v) => OnRightReplaced(i, v, v);
            _rightCollectionWrappper.ItemAdded    += (s, i, v) => OnRightAdded(i, v);
            _rightCollectionWrappper.ItemRemoved  += (s, i, v) => OnRightRemoved(i, v);
            _rightCollectionWrappper.ItemReplaced += (s, i, o, n) => OnRightReplaced(i, o, n);
            _rightCollectionWrappper.ItemMoved    += (s, o, n, v) => OnRightMoved(o, n, v);
            _rightCollectionWrappper.ItemsReset   += s => OnRightReset(s);
        }
        public ActiveValueListUnwrapper(IReadOnlyList <TSource> source, IActiveValue <TParameter> parameter, Func <TSource, IActiveValue <TResult> > selector, IEnumerable <string> sourcePropertiesToWatch, IEnumerable <string> parameterPropertiesToWatch)
        {
            _selector = selector;

            _valueStore = new ObservableList <ValueStore, TResult>(store => store.Value);
            _valueStore.PropertyChanged   += (s, e) => PropertyChanged?.Invoke(this, e);
            _valueStore.CollectionChanged += (s, e) => CollectionChanged?.Invoke(this, e);

            _sourceList = new CollectionWrapper <TSource>(source, sourcePropertiesToWatch?.ToArray());
            _sourceList.ItemModified += (s, i, v) => ItemModified(i, v);
            _sourceList.ItemAdded    += (s, i, v) => OnAdded(i, v);
            _sourceList.ItemRemoved  += (s, i, v) => OnRemoved(i, v);
            _sourceList.ItemReplaced += (s, i, o, n) => OnReplaced(i, o, n);
            _sourceList.ItemMoved    += (s, o, n, v) => OnMoved(o, n, v);
            _sourceList.ItemsReset   += s => OnReset(s);

            if (parameter != null)
            {
                _parameterWatcher = new ValueWatcher <TParameter>(parameter, parameterPropertiesToWatch);
                _parameterWatcher.ValueOrValuePropertyChanged += () => OnParameterChanged();
            }

            OnReset(_sourceList);
        }