예제 #1
0
        /// <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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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();
        }
예제 #5
0
 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();
 }
예제 #6
0
        /// <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);
            }
        }
예제 #7
0
        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);
                }
            }
        }
예제 #8
0
        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()
                });
            }
        }
예제 #9
0
        /// <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)));
            }
        }
예제 #10
0
        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();
        }