public ChannelProvider <TChannel> GetChannelProvider <TChannel>(ChannelAccessor <T, TChannel> channelAccessor,
                                                                        KeyAccessor <TChannel, TKey> messageKeyAccessor,
                                                                        InstanceChannelPolicy <T, TChannel> channelPolicy)
        {
            Guard.AgainstNull(channelAccessor, "channelAccessor");
            Guard.AgainstNull(messageKeyAccessor, "messageKeyAccessor");

            if (_cache == null)
            {
                Func <TKey, T> missingInstanceProvider = _configurator.GetConfiguredInstanceFactory();
                _cache = new Cache <TKey, T>(missingInstanceProvider);
            }

            Cache <TKey, T> cache = _cache;

            var instanceProvider = new DelegateChannelProvider <TChannel>(msg =>
            {
                TKey key = messageKeyAccessor(msg);

                T instance;

                if (cache.Has(key))
                {
                    if (!channelPolicy.IsHandledByExistingInstance(msg))
                    {
                        channelPolicy.WasNotHandled(msg);
                        return(null);
                    }

                    instance = cache[key];
                }
                else
                {
                    if (!channelPolicy.CanCreateInstance(msg, out instance))
                    {
                        channelPolicy.WasNotHandled(msg);
                        return(null);
                    }

                    cache.Add(key, instance);
                }

                return(channelAccessor(instance));
            });

            FiberProvider <TKey> fiberProvider = _configurator.GetConfiguredProvider();

            var channelProvider = new CacheChannelProvider <TChannel, TKey>(fiberProvider, instanceProvider, messageKeyAccessor);

            return(channelProvider);
        }