public void Subscribe(string objectId, IEventDescription eventDescription, ISerializer serializer, Delegate handler, object proxy) { if (_disposed) { throw new ObjectDisposedException(nameof(EventHandlersRepository)); } var eventId = new EventId { ObjectId = objectId, EventName = eventDescription.Name }; lock (_events) { if (!_events.TryGetValue(eventId, out var subscriptionRepository)) { var subscribeMessage = new SubscribeEventMessage(_clientHostAddress, objectId, eventDescription.Name); _outputChannel.SendWithAck(subscribeMessage); subscriptionRepository = new SubscriptionRepository(eventDescription, serializer, _eloquentClient); _events.Add(eventId, subscriptionRepository); } subscriptionRepository.Subscribe(handler, proxy); } }
/// <inheritdoc /> public object Connect(Type type, string objectId) { var contractDescription = _contractDescriptionFactory.Create(type); //Send ConnectObjectMessage to ensure that object is hosted var connectObjectMessage = new ConnectMessage(_clientHostAddress, objectId); _outputChannel.SendWithAck(connectObjectMessage); var knownTypes = contractDescription.GetTypes(); var serializer = _serializerFactory.Create(typeof(object), knownTypes); var interceptor = new ClientInterceptor(contractDescription); var proxy = _proxyGenerator.CreateInterfaceProxyWithoutTarget(type, interceptor); var connection = new Connection(objectId, proxy, _eventHandlersRepository, contractDescription, serializer, this, _outputChannel, _clientHostAddress); interceptor.Subscribe(connection); lock (_objectIds) { RemoveDeadObjectIds(); _objectIds.Add(new Tuple <string, WeakReference>(objectId, new WeakReference(proxy))); } return(proxy); }
/// <summary> /// Creates an EloquentObjects client with ability to specify custom settings and dependencies. /// </summary> /// <param name="serverAddress">Address of the server that hosts object. Can be prefixed with 'tcp://' for TCP binding or 'pipe://' for Named Pipes binding</param> /// <param name="clientAddress">Client-side address that is used to send server-to-client events. Can be prefixed with 'tcp://' for TCP binding or 'pipe://' for Named Pipes binding</param> /// <param name="settings">Custom settings</param> /// <param name="serializerFactory">Factory that can create serializer to be used for serializing/deserializing data sent between server and client</param> /// <exception cref="ArgumentException">Client Uri scheme should match server Uri scheme</exception> public EloquentClient(string serverAddress, string clientAddress, EloquentSettings settings, [CanBeNull] ISerializerFactory serializerFactory = null) { _serializerFactory = serializerFactory ?? new DefaultSerializerFactory(); var serverUri = new Uri(serverAddress); var clientUri = new Uri(clientAddress); var serverScheme = serverUri.GetComponents(UriComponents.Scheme, UriFormat.Unescaped); var clientScheme = clientUri.GetComponents(UriComponents.Scheme, UriFormat.Unescaped); if (serverScheme != clientScheme) { throw new ArgumentException("Client Uri scheme should match server Uri scheme"); } var binding = new BindingFactory().Create(serverScheme, settings); var serverHostAddress = HostAddress.CreateFromUri(serverUri); _clientHostAddress = HostAddress.CreateFromUri(clientUri); _contractDescriptionFactory = new CachedContractDescriptionFactory(new ContractDescriptionFactory()); _proxyGenerator = new ProxyGenerator(); try { _inputChannel = binding.CreateInputChannel(_clientHostAddress); } catch (Exception e) { throw new IOException("Failed creating input channel", e); } try { _outputChannel = binding.CreateOutputChannel(serverHostAddress); } catch (Exception e) { throw new IOException("Connection failed. Server not found.", e); } _inputChannel.Start(); //Send HelloMessage to create a session var helloMessage = new HelloMessage(_clientHostAddress); _outputChannel.SendWithAck(helloMessage); _eventHandlersRepository = new EventHandlersRepository(_outputChannel, _clientHostAddress, this); _sessionAgent = new SessionAgent(binding, _inputChannel, _outputChannel, _clientHostAddress, _eventHandlersRepository); }