/// <summary>
        /// Constructs a DefaultRemoteManager listening on the specified address and
        /// a specific port.
        /// </summary>
        /// <param name="localAddress">The address to listen on</param>
        /// <param name="tcpPortProvider">Tcp port provider</param>
        /// <param name="streamingCodec">Streaming codec</param>
        /// <param name="tcpClientFactory">provides TcpClient for given endpoint</param>
        internal StreamingRemoteManager(IPAddress localAddress,
                                        ITcpPortProvider tcpPortProvider,
                                        IStreamingCodec <T> streamingCodec,
                                        ITcpClientConnectionFactory tcpClientFactory)
        {
            if (localAddress == null)
            {
                throw new ArgumentNullException("localAddress");
            }

            _tcpClientFactory  = tcpClientFactory;
            _observerContainer = new ObserverContainer <T>();
            _cachedClients     = new Dictionary <IPEndPoint, ProxyObserver>();
            _remoteEventCodec  = new RemoteEventStreamingCodec <T>(streamingCodec);

            // Begin to listen for incoming messages
            _server = new StreamingTransportServer <IRemoteEvent <T> >(localAddress,
                                                                       _observerContainer,
                                                                       tcpPortProvider,
                                                                       _remoteEventCodec);
            _server.Run();

            LocalEndpoint = _server.LocalEndpoint;
            Identifier    = new SocketRemoteIdentifier(LocalEndpoint);
        }
        /// <summary>
        /// Constructs a DefaultRemoteManager listening on the specified address and any
        /// available port.
        /// </summary>
        /// <param name="localAddress">The address to listen on</param>
        /// <param name="port">The port to listen on</param>
        /// <param name="codec">The codec used for serializing messages</param>
        /// <param name="tcpPortProvider">provides port numbers to listen</param>
        internal DefaultRemoteManager(IPAddress localAddress, int port, ICodec <T> codec, ITcpPortProvider tcpPortProvider)
        {
            if (localAddress == null)
            {
                throw new ArgumentNullException("localAddress");
            }
            if (port < 0)
            {
                throw new ArgumentException("Listening port must be greater than or equal to zero");
            }
            if (codec == null)
            {
                throw new ArgumentNullException("codec");
            }

            _observerContainer = new ObserverContainer <T>();
            _codec             = new RemoteEventCodec <T>(codec);
            _cachedClients     = new Dictionary <IPEndPoint, ProxyObserver>();

            IPEndPoint localEndpoint = new IPEndPoint(localAddress, port);

            // Begin to listen for incoming messages
            _server = new TransportServer <IRemoteEvent <T> >(localEndpoint, _observerContainer, _codec,
                                                              tcpPortProvider);
            _server.Run();

            LocalEndpoint = _server.LocalEndpoint;
            Identifier    = new SocketRemoteIdentifier(LocalEndpoint);
        }
        /// <summary>
        /// Constructs a DefaultRemoteManager. Does not listen for incoming messages.
        /// </summary>
        /// <param name="codec">The codec used for serializing messages</param>
        internal DefaultRemoteManager(ICodec <T> codec)
        {
            using (LOGGER.LogFunction("DefaultRemoteManager::DefaultRemoteManager"))
            {
                if (codec == null)
                {
                    throw new ArgumentNullException("codec");
                }

                _observerContainer = new ObserverContainer <T>();
                _codec             = new RemoteEventCodec <T>(codec);
                _cachedClients     = new Dictionary <IPEndPoint, ProxyObserver>();

                LocalEndpoint = new IPEndPoint(NetworkUtils.LocalIPAddress, 0);
                Identifier    = new SocketRemoteIdentifier(LocalEndpoint);
            }
        }
        /// <summary>
        /// Constructs a DefaultRemoteManager. Does not listen for incoming messages.
        /// </summary>
        /// <param name="localAddressProvider">The local address provider</param>
        /// <param name="codec">The codec used for serializing messages</param>
        /// <param name="tcpClientFactory">provides TcpClient for given endpoint</param>
        internal DefaultRemoteManager(
            ILocalAddressProvider localAddressProvider,
            ICodec <T> codec,
            ITcpClientConnectionFactory tcpClientFactory)
        {
            using (LOGGER.LogFunction("DefaultRemoteManager::DefaultRemoteManager"))
            {
                if (codec == null)
                {
                    throw new ArgumentNullException("codec");
                }

                _tcpClientFactory  = tcpClientFactory;
                _observerContainer = new ObserverContainer <T>();
                _codec             = new RemoteEventCodec <T>(codec);
                _cachedClients     = new Dictionary <IPEndPoint, ProxyObserver>();

                LocalEndpoint = new IPEndPoint(localAddressProvider.LocalAddress, 0);
                Identifier    = new SocketRemoteIdentifier(LocalEndpoint);
            }
        }