/// <summary> /// Registers a recipient for a type of message TMessage. /// The action parameter will be executed when a corresponding /// message is sent. See the receiveDerivedMessagesToo parameter /// for details on how messages deriving from TMessage (or, if TMessage is an interface, /// messages implementing TMessage) can be received too. /// <para>Registering a recipient does not create a hard reference to it, /// so if this recipient is deleted, no memory leak is caused.</para> /// </summary> /// <typeparam name="TMessage">The type of message that the recipient registers /// for.</typeparam> /// <param name="recipient">The recipient that will receive the messages.</param> /// <param name="token">A token for a messaging channel. If a recipient registers /// using a token, and a sender sends a message using the same token, then this /// message will be delivered to the recipient. Other recipients who did not /// use a token when registering (or who used a different token) will not /// get the message. Similarly, messages sent without any token, or with a different /// token, will not be delivered to that recipient.</param> /// <param name="receiveDerivedMessagesToo">If true, message types deriving from /// TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage /// and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage /// and setting receiveDerivedMessagesToo to true will send SendOrderMessage /// and ExecuteOrderMessage to the recipient that registered. /// <para>Also, if TMessage is an interface, message types implementing TMessage will also be /// transmitted to the recipient. For example, if a SendOrderMessage /// and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage /// and setting receiveDerivedMessagesToo to true will send SendOrderMessage /// and ExecuteOrderMessage to the recipient that registered.</para> /// </param> /// <param name="action">The action that will be executed when a message /// of type TMessage is sent. IMPORTANT: If the action causes a closure, /// you must set keepTargetAlive to true to avoid side effects. </param> /// <param name="keepTargetAlive">If true, the target of the Action will /// be kept as a hard reference, which might cause a memory leak. You should only set this /// parameter to true if the action is using closures. See /// http://galasoft.ch/s/mvvmweakaction. </param> public virtual void Register <TMessage>( object recipient, object token, bool receiveDerivedMessagesToo, Action <TMessage> action, bool keepTargetAlive = false) { lock (_registerLock) { var messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients; if (receiveDerivedMessagesToo) { if (_recipientsOfSubclassesAction == null) { _recipientsOfSubclassesAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = _recipientsOfSubclassesAction; } else { if (_recipientsStrictAction == null) { _recipientsStrictAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = _recipientsStrictAction; } lock (recipients) { List <WeakActionAndToken> list; if (!recipients.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); recipients.Add(messageType, list); } else { list = recipients[messageType]; } var weakAction = new WeakAction <TMessage>(recipient, action, keepTargetAlive); var item = new WeakActionAndToken { Action = weakAction, Token = token }; list.Add(item); } } RequestCleanup(); }
public void Subscribe <TMessage>(object recipient, Action <TMessage> action, ThreadOption threadOption, string?tag) where TMessage : Message { lock (this.registerLock) { var messageType = typeof(TMessage); this.recipientsOfSubclassesAction ??= new Dictionary <Type, List <WeakActionAndToken> >(); List <WeakActionAndToken> list; if (!this.recipientsOfSubclassesAction.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); this.recipientsOfSubclassesAction.Add(messageType, list); } else { list = this.recipientsOfSubclassesAction[messageType]; } var item = new WeakActionAndToken { Recipient = recipient, ThreadOption = threadOption, Action = action, Tag = tag }; list.Add(item); } }
public void Register <TMessage>(object recipient, object token, Action <TMessage> action) { Type messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients = _recipientsStrictAction; lock (recipients) { List <WeakActionAndToken> list; if (!recipients.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); recipients.Add(messageType, list); } else { list = recipients[messageType]; } var weakAction = new WeakAction <TMessage>(recipient, action); var item = new WeakActionAndToken { Action = weakAction, Token = token }; list.Add(item); } CleanupList(_recipientsStrictAction); }
/// <summary> /// Registers a recipient for a type of message TMessage. The action parameter will be executed when a corresponding message is sent. See the receiveDerivedMessagesToo parameter /// for details on how messages deriving from TMessage (or, if TMessage is an interface, messages implementing TMessage) can be received too. /// <para>Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.</para> /// </summary> /// <typeparam name="TMessage">The type of message that the recipient registers for.</typeparam> /// <param name="recipient">The recipient that will receive the messages.</param> /// <param name="token"> /// A token for a messaging channel. If a recipient registers using a token, and a sender sends a message using the same token, then this /// message will be delivered to the recipient. Other recipients who did not use a token when registering (or who used a different token) will not /// get the message. Similarly, messages sent without any token, or with a different token, will not be delivered to that recipient. /// </param> /// <param name="receiveDerivedMessagesToo">If true, message types deriving from TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage /// and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage and setting receiveDerivedMessagesToo to true will send SendOrderMessage /// and ExecuteOrderMessage to the recipient that registered. /// <para> /// Also, if TMessage is an interface, message types implementing TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage /// and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage and setting receiveDerivedMessagesToo to true will send SendOrderMessage /// and ExecuteOrderMessage to the recipient that registered. /// </para> /// </param> /// <param name="action"> /// The action that will be executed when a message of type TMessage is sent. IMPORTANT: Note that closures are not supported at the moment /// due to the use of WeakActions (see http://stackoverflow.com/questions/25730530/). /// </param> public virtual void Register <TMessage>(Object recipient, Object token, Boolean receiveDerivedMessagesToo, Action <TMessage> action) { lock (this.registerLock) { Type messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients; if (receiveDerivedMessagesToo) { if (this.recipientsOfSubclassesAction == null) { this.recipientsOfSubclassesAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = this.recipientsOfSubclassesAction; } else { if (this.recipientsStrictAction == null) { this.recipientsStrictAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = this.recipientsStrictAction; } lock (recipients) { List <WeakActionAndToken> list; if (!recipients.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); recipients.Add(messageType, list); } else { list = recipients[messageType]; } WeakAction <TMessage> weakAction = new WeakAction <TMessage>(recipient, action); WeakActionAndToken item = new WeakActionAndToken { Action = weakAction, Token = token }; list.Add(item); } } this.RequestCleanup(); }
public virtual void Register <TMessage>(object recipient, object token, bool receiveDerivedMessagesToo, Action <TMessage> action) { lock (this._registerLock) { Dictionary <Type, List <WeakActionAndToken> > dictionary; Type key = typeof(TMessage); if (receiveDerivedMessagesToo) { if (this._recipientsOfSubclassesAction == null) { this._recipientsOfSubclassesAction = new Dictionary <Type, List <WeakActionAndToken> >(); } dictionary = this._recipientsOfSubclassesAction; } else { if (this._recipientsStrictAction == null) { this._recipientsStrictAction = new Dictionary <Type, List <WeakActionAndToken> >(); } dictionary = this._recipientsStrictAction; } lock (dictionary) { List <WeakActionAndToken> list; if (!dictionary.ContainsKey(key)) { list = new List <WeakActionAndToken>(); dictionary.Add(key, list); } else { list = dictionary[key]; } WeakAction <TMessage> action2 = new WeakAction <TMessage>(recipient, action); WeakActionAndToken item = new WeakActionAndToken { Action = action2, Token = token }; list.Add(item); } } this.Cleanup(); }
/// <summary> /// Registers a recipient of messages of specified type. /// </summary> public static void Register <TMessage>(object recipient, object token, Action <TMessage> action, bool keepTargetAlive = false) { lock (_recipients) { var messageType = typeof(TMessage); if (!_recipients.TryGetValue(messageType, out var actions)) { actions = new List <WeakActionAndToken>(); _recipients.Add(messageType, actions); } var weakAction = new WeakAction <TMessage>(recipient, action, keepTargetAlive); var actionAndToken = new WeakActionAndToken { Action = weakAction, Token = token }; actions.Add(actionAndToken); } }
public void Register <TMessage>(object recipient, object token, Action <TMessage> action) { lock (_registerLock) { var messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients; if (_registerActions == null) { _registerActions = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = _registerActions; lock (recipients) { List <WeakActionAndToken> list; if (!recipients.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); recipients.Add(messageType, list); } else { list = recipients[messageType]; } var weakAction = new WeakAction <TMessage>(action); var item = new WeakActionAndToken { Action = weakAction, Token = token, Recipient = recipient, }; list.Add(item); } } }
public async Task SubscribeAsync(object recipient, string topic, Action <string> action) { if (recipient == null || topic == null || action == null) { return; } if (!client.IsConnected) { if (!await TryConnectAsync()) { logger.Warn("Subscribe [{0}] failed, because client not connected to a server.", topic); return; } } await client.SubscribeAsync(topic); if (!recipientsStrictAction.ContainsKey(topic)) { List <WeakActionAndToken> actions = new List <WeakActionAndToken>(); WeakActionAndToken item = new WeakActionAndToken() { Action = new WeakAction <string>(recipient, action), Token = recipient.GetHashCode(), }; actions.Add(item); recipientsStrictAction.Add(topic, actions); } else { recipientsStrictAction[topic].Add( new WeakActionAndToken() { Action = new WeakAction <string>(recipient, action), Token = recipient.GetHashCode() }); } }
/// <summary> /// Checks whether a particular message is registered with the given recipient. /// </summary> /// <param name="recipient"> /// The recipient that will receive the messages. /// </param> /// <param name="receiveDerivedMessagesToo"> /// If true, message types deriving from TMessage will also be transmitted to the recipient. /// </param> /// <typeparam name="TMessage"> /// The type of message that the recipient registers for. /// </typeparam> /// <returns> /// True if the message is currently registered; otherwise, false. /// </returns> public bool IsRegistered <TMessage>(object recipient, bool receiveDerivedMessagesToo) { Type messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients; if (receiveDerivedMessagesToo) { if (this.recipientsOfSubclassesAction == null) { this.recipientsOfSubclassesAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = this.recipientsOfSubclassesAction; } else { if (this.recipientsStrictAction == null) { this.recipientsStrictAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = this.recipientsStrictAction; } lock (recipients) { List <WeakActionAndToken> list = new List <WeakActionAndToken>(); if (recipients.ContainsKey(messageType)) { list = recipients[messageType]; } WeakActionAndToken registeredRecipient = list.FirstOrDefault(item => item.Action.IsAlive && item.Action.Target.Equals(recipient)); // If a WeakActionAndToken for the recipient and the action is alive, it's registered. return(!registeredRecipient.Equals(default(WeakActionAndToken))); } }
private void Register <TMessage>( object recipient, object token, bool receiveDerivedMessagesToo, Action <TMessage> action, Predicate <TMessage> condition) { lock (registerLock) { var messageType = typeof(TMessage); Dictionary <Type, List <WeakActionAndToken> > recipients; if (receiveDerivedMessagesToo) { if (recipientsOfSubclassesAction == null) { recipientsOfSubclassesAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = recipientsOfSubclassesAction; } else { if (recipientsStrictAction == null) { recipientsStrictAction = new Dictionary <Type, List <WeakActionAndToken> >(); } recipients = recipientsStrictAction; } lock (recipients) { List <WeakActionAndToken> list; if (!recipients.ContainsKey(messageType)) { list = new List <WeakActionAndToken>(); recipients.Add(messageType, list); } else { list = recipients[messageType]; } var weakAction = new WeakAction <TMessage>(recipient, action); var item = new WeakActionAndToken { Action = weakAction, Token = token, Condition = condition }; list.Add(item); } } Cleanup(); }