public static void AddUser <T>(UrlSubscription <T> user)
        {
            //attempt to get type subscription
            SubscriptionsByType subscriptionsByUser;

            SubscriptionsByType.TryGetValue(typeof(T), out subscriptionsByUser);

            //if unable to get attempt to add
            if (subscriptionsByUser == null)
            {
                subscriptionsByUser = new SubscriptionsByType()
                {
                    SubscriptionType = typeof(T)
                };

                //add new type subscription
                var wasAdded = SubscriptionsByType.TryAdd(typeof(T), subscriptionsByUser);

                //if add failed then likely another thread was adding at the same time, try again
                if (!wasAdded)
                {
                    AddUser <T>(user);
                    return;
                }
            }


            //attempt to get user subscription
            SubscriptionsByUser subscriptionsByUrl;

            subscriptionsByUser.SubscriptionsByUser.TryGetValue(user.ConnectionId, out subscriptionsByUrl);

            //if unable to get attempt to add
            if (subscriptionsByUrl == null)
            {
                subscriptionsByUrl = new SubscriptionsByUser()
                {
                    SubscriptionType = typeof(T)
                };

                //add new type subscription
                var wasAdded = subscriptionsByUser.SubscriptionsByUser.TryAdd(user.ConnectionId, subscriptionsByUrl);

                //if add failed then likely another thread was adding at the same time, try again
                if (!wasAdded)
                {
                    AddUser <T>(user);
                    return;
                }
            }

            //add or update value with new value
            subscriptionsByUrl.SubscriptionsByUrl.AddOrUpdate(user.Url, user, (key, oldValue) => oldValue = user);
        }
        // DO NOT REMOVE, ACCESSED BY STRING, I KNOW IT'S NASTY
        public static List <UserSubscriptionResult> GetSubscribed <T>(SubscriptionsByType subscriptionsByUser, List <ChangedObject> values)
        {
            var results = new List <UserSubscriptionResult>();

            foreach (var user in subscriptionsByUser.SubscriptionsByUser)
            {
                if (user.Value == null)
                {
                    continue;
                }

                var userResults = new UserSubscriptionResult
                {
                    ConnectionId = user.Key
                };

                foreach (var url in user.Value.SubscriptionsByUrl)
                {
                    if (url.Value == null)
                    {
                        continue;
                    }

                    IURLSubscription    interfaceSubscription = url.Value;
                    UrlSubscription <T> typedSubscription     = (UrlSubscription <T>)interfaceSubscription;

                    foreach (var value in values)
                    {
                        var typedObject = (T)value.Object;

                        if (typedSubscription.Query == null || typedSubscription.Query.Invoke(typedObject))
                        {
                            var newUrl = new UrlSubscriptionResults
                            {
                                Url = url.Key
                            };

                            newUrl.Data.Add(value);

                            userResults.Urls.Add(newUrl);
                        }
                    }
                }

                if (userResults.Urls.Any())
                {
                    results.Add(userResults);
                }
            }

            return(results);
        }