/// <summary>
        /// Detach an event listener
        /// </summary>
        /// <param name="address">the address of the container</param>
        /// <param name="event">the event to remove</param>
        public void Detach(string address, OscMessageEvent @event)
        {
            if (@event == null)
            {
                throw new ArgumentNullException("event");
            }

            if (OscAddress.IsValidAddressLiteral(address) == true)
            {
                OscLiteralEvent container;

                lock (m_Lock)
                {
                    if (m_LiteralAddresses.TryGetValue(address, out container) == false)
                    {
                        // no container was found so abort
                        return;
                    }
                }
                // unregiser the event
                container.Event -= @event;

                // if the container is now empty remove it from the lookup
                if (container.IsNull == true)
                {
                    m_LiteralAddresses.Remove(container.Address);
                }
            }
            else if (OscAddress.IsValidAddressPattern(address) == true)
            {
                OscPatternEvent container;
                OscAddress      oscAddress = new OscAddress(address);

                lock (m_Lock)
                {
                    if (m_PatternAddresses.TryGetValue(oscAddress, out container) == false)
                    {
                        // no container was found so abort
                        return;
                    }
                }

                // unregiser the event
                container.Event -= @event;

                // if the container is now empty remove it from the lookup
                if (container.IsNull == true)
                {
                    m_PatternAddresses.Remove(container.Address);
                }
            }
            else
            {
                throw new ArgumentException(String.Format(Strings.Container_IsValidContainerAddress, address), "address");
            }
        }
        /// <summary>
        /// Attach an event listener on to the given address
        /// </summary>
        /// <param name="address">the address of the contianer</param>
        /// <param name="event">the event to attach</param>
        public void Attach(string address, OscMessageEvent @event)
        {
            if (@event == null)
            {
                throw new ArgumentNullException("event");
            }

            // if the address is a literal then add it to the literal lookup
            if (OscAddress.IsValidAddressLiteral(address) == true)
            {
                OscLiteralEvent container;

                lock (m_Lock)
                {
                    if (m_LiteralAddresses.TryGetValue(address, out container) == false)
                    {
                        // no container was found so create one
                        container = new OscLiteralEvent(address);

                        // add it to the lookup
                        m_LiteralAddresses.Add(address, container);
                    }
                }

                // attach the event
                container.Event += @event;
            }
            // if the address is a pattern add it to the pattern lookup
            else if (OscAddress.IsValidAddressPattern(address) == true)
            {
                OscPatternEvent container;
                OscAddress      oscAddress = new OscAddress(address);

                lock (m_Lock)
                {
                    if (m_PatternAddresses.TryGetValue(oscAddress, out container) == false)
                    {
                        // no container was found so create one
                        container = new OscPatternEvent(oscAddress);

                        // add it to the lookup
                        m_PatternAddresses.Add(oscAddress, container);
                    }
                }

                // attach the event
                container.Event += @event;
            }
            else
            {
                throw new ArgumentException(String.Format(Strings.Container_IsValidContainerAddress, address), "address");
            }
        }