private async Task <Guid> SubscribeAsync(bool includeValues, IPredicate predicate, bool hasPredicate, TKey key, bool hasKey, Action <DictionaryEventHandlers <TKey, TValue> > handle, CancellationToken cancellationToken)
        {
            if (hasKey && key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (hasPredicate && predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }
            if (handle == null)
            {
                throw new ArgumentNullException(nameof(handle));
            }

            var handlers = new DictionaryEventHandlers <TKey, TValue>();

            handle(handlers);

            var flags = HDictionaryEventTypes.Nothing;

            foreach (var handler in handlers)
            {
                flags |= handler.EventType;
            }

            // 0: no entryKey, no predicate
            // 1: entryKey, no predicate
            // 2: no entryKey, predicate
            // 3: entryKey, predicate
            var mode = (hasKey ? 1 : 0) + (hasPredicate ? 2 : 0);

            var subscribeRequest = mode switch
            {
                0 => MapAddEntryListenerCodec.EncodeRequest(Name, includeValues, (int)flags, Cluster.IsSmartRouting),
                1 => MapAddEntryListenerToKeyCodec.EncodeRequest(Name, ToData(key), includeValues, (int)flags, Cluster.IsSmartRouting),
                2 => MapAddEntryListenerWithPredicateCodec.EncodeRequest(Name, ToData(predicate), includeValues, (int)flags, Cluster.IsSmartRouting),
                3 => MapAddEntryListenerToKeyWithPredicateCodec.EncodeRequest(Name, ToData(key), ToData(predicate), includeValues, (int)flags, Cluster.IsSmartRouting),
                _ => throw new NotSupportedException()
            };

            var subscription = new ClusterSubscription(
                subscribeRequest,
                ReadSubscribeResponse,
                CreateUnsubscribeRequest,
                ReadUnsubscribeResponse,
                HandleEventAsync,
                new MapSubscriptionState(mode, Name, handlers));

            await Cluster.Events.InstallSubscriptionAsync(subscription, cancellationToken).CAF();

            return(subscription.Id);
        }
 public MapSubscriptionState(int mode, string name, DictionaryEventHandlers <TKey, TValue> handlers)
     : base(name, handlers)
 {
     Mode = mode;
 }