提问者:小点点

如何实现回调以通知使用某个类的人? [已关闭]


例如,我有一个跟踪商品库存的类。 当股票下跌时,我必须添加一个回调来通知使用它的人股票正在下跌(例如,当剩下的对象不到10个时)。 我明白我必须将回调添加到Remove方法中,但是我如何实现它,以及如何在不使用控制台的情况下实现它呢?


共2个答案

匿名用户

您可以使用委托,也可以使用Mediatr等更复杂的东西

匿名用户

下面是一个工作示例,如果你想查看一下的话:

Blazor聊天https://github.com/datajuggler/blazorchat

此示例需要SQL Server或SQL Server Express。

它使用这个名为订阅者服务的类:

#region using statements

using DataJuggler.Blazor.Components;
using DataJuggler.UltimateHelper.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using BlazorChat.Enumerations;
using System.Threading.Tasks;
using System.Transactions;

#endregion

namespace BlazorChat.Services
{

    #region class SubscriberService
    /// <summary>
    /// This class is used to subscribe to services, so other windows get a notification a new message 
    /// came in.
    /// </summary>
    public class SubscriberService
    {

        #region Private Variables
        private int count;
        private Guid serverId;
        private List<SubscriberMessage> messages;
        private List<SubscriberCallback> subscribers;
        #endregion

        #region Constructor
        /// <summary>
        /// Create a new instance of a 'SubscriberService' object.
        /// </summary>
        public SubscriberService()
        {
            // Create a new Guid
            this.ServerId = Guid.NewGuid();
            Subscribers = new List<SubscriberCallback>();
            Messages = new List<SubscriberMessage>();
        }
        #endregion

        #region Methods

            #region BroadcastMessage(SubscriberMessage message)
            /// <summary>
            /// This method Broadcasts a Message to everyone that ins't blocked.
            /// What it actually does is notify the Listener that they need to get new messages.
            /// Note To Self: Add Blocked Feature.
            /// </summary>
            public void BroadcastMessage(SubscriberMessage message)
            {
                // if the value for HasSubscribers is true
                if ((HasSubscribers) && (NullHelper.Exists(message)))
                {
                    // if this is a System Message
                    if (!message.IsSystemMessage)
                    {  
                        // if there are already messages
                        if (ListHelper.HasOneOrMoreItems(messages))
                        {
                            // Insert at the top
                            Messages.Insert(0, message);
                        }
                        else
                        {
                            // Add this message
                            Messages.Add(message);
                        }
                    }

                    // Iterate the collection of SubscriberCallback objects
                    foreach (SubscriberCallback subscriber in Subscribers)
                    {
                        // Send to everyone but this user
                        if ((subscriber.HasCallback) && (subscriber.Id != message.FromId))
                        {
                            // to do: Add if not blocked

                            // send the message
                            subscriber.Callback(message);
                        }
                    }                    
                }
            }
            #endregion

            #region FindSubscriber(Guid id)
            /// <summary>
            /// This method returns the Subscriber
            /// </summary>
            public SubscriberCallback FindSubscriber(Guid id)
            {
                // initial value
                SubscriberCallback subscriber = null;

                // if the id Guid is set and the Subscribers exist
                if ((id != Guid.Empty) && (HasSubscribers))
                {
                    // Set the return value
                    subscriber = Subscribers.FirstOrDefault(x => x.Id == id);
                }

                // return value
                return subscriber;
            }
            #endregion

            #region GetMessages(Guid id, int count)
            /// <summary>
            /// This method returns a list of Messages
            /// </summary>
            public List<SubscriberMessage> GetBroadcastMessages(Guid id, int count)
            {
                // initial value
                List<SubscriberMessage> messages = this.Messages.Where(x => ((!x.IsPrivate) || (x.FromId == id) || (x.ToId == id))).Take(count).ToList();

                // return value
                return messages;
            }
            #endregion

            #region GetSubscriberNames()
            /// <summary>
            /// This method returns a list of Subscriber Names ()
            /// </summary>
            public List<SubscriberCallback> GetSubscriberNames()
            {
                // initial value
                List<SubscriberCallback> subscriberNames = null;

                // if the value for HasSubscribers is true
                if (HasSubscribers)
                {
                    // Set The return value in alphabetical order
                    subscriberNames = Subscribers.OrderBy(x => x.Name).ToList();
                }

                // return value
                return subscriberNames;
            }
            #endregion

            #region SendPrivateMessage(SubscriberCallback subscriber, SubscriberMessage message)
            /// <summary>
            /// This method Send Private Message
            /// </summary>
            public void SendPrivateMessage(SubscriberCallback subscriber, SubscriberMessage message)
            {
                // if the message and the subscriber exists and the subscriber has a callback
                if ((NullHelper.Exists(message, subscriber)) && (subscriber.HasCallback))
                {
                    // if there are already messages
                    if (ListHelper.HasOneOrMoreItems(messages))
                    {
                        // Insert at the top
                        Messages.Insert(0, message);
                    }
                    else
                    {
                        // Add this message
                        Messages.Add(message);
                    }

                    // Send the message to the user
                    subscriber.Callback(message);
                }
            }
            #endregion

            #region Subscribe(string subscriberName)
            /// <summary>
            /// method returns a message with their id
            /// </summary>
            public SubscriberMessage Subscribe(SubscriberCallback subscriber)
            {
                // initial value
                SubscriberMessage message = null;

                // If the subscriber object exists
                if ((NullHelper.Exists(subscriber)) && (HasSubscribers))
                {
                    // Add this item
                    Subscribers.Add(subscriber);    

                    // return a test message for now
                    message = new SubscriberMessage();

                    // set the message return properties
                    message.FromName = "Subscriber Service";
                    message.FromId = ServerId;
                    message.ToName = subscriber.Name;
                    message.ToId = subscriber.Id;
                    message.Data = Subscribers.Count.ToString();
                    message.Text = "Subscribed";
                }

                // return value
                return message;
            }
            #endregion

            #region Unsubscribe(Guid id)
            /// <summary>
            /// This method Unsubscribe
            /// </summary>
            public void Unsubscribe(Guid id)
            {
                // if the value for HasSubscribers is true
                if ((HasSubscribers) && (Subscribers.Count > 0))
                {
                    // attempt to find this callback
                    SubscriberCallback callback = Subscribers.FirstOrDefault(x => x.Id == id);

                    // If the callback object exists
                    if (NullHelper.Exists(callback))
                    {
                        // Remove this item
                        Subscribers.Remove(callback);

                         // create a new message
                        SubscriberMessage message = new SubscriberMessage();

                        // set the message return properties
                        message.FromId = ServerId;
                        message.FromName = "Subscriber Service";
                        message.Text = callback.Name + " has left the conversation.";
                        message.ToId = Guid.Empty;
                        message.ToName = "Room";
                        message.IsSystemMessage = true;

                        // Broadcast the message to everyone
                        BroadcastMessage(message);
                    }
                }
            }
            #endregion

        #endregion

        #region Properties

            #region Count
            /// <summary>
            /// This property gets or sets the value for 'Count'.
            /// </summary>
            public int Count
            {
                get { return count; }
                set { count = value; }
            }
            #endregion

            #region HasSubscribers
            /// <summary>
            /// This property returns true if this object has a 'Subscribers'.
            /// </summary>
            public bool HasSubscribers
            {
                get
                {
                    // initial value
                    bool hasSubscribers = (this.Subscribers != null);

                    // return value
                    return hasSubscribers;
                }
            }
            #endregion

            #region Messages
            /// <summary>
            /// This property gets or sets the value for 'Messages'.
            /// </summary>
            public List<SubscriberMessage> Messages
            {
                get { return messages; }
                set { messages = value; }
            }
            #endregion

            #region ServerId
            /// <summary>
            /// This property gets or sets the value for 'ServerId'.
            /// </summary>
            public Guid ServerId
            {
                get { return serverId; }
                set { serverId = value; }
            }
            #endregion

            #region Subscribers
            /// <summary>
            /// This property gets or sets the value for 'Subscribers'.
            /// </summary>
            public List<SubscriberCallback> Subscribers
            {
                get { return subscribers; }
                set { subscribers = value; }
            }
            #endregion

        #endregion

    }
    #endregion

}

SubscriberService保留一个订阅者列表,这些订阅者都是这个类SubscriberCallback的一部分,其中包括一个名称,一个Guid Id和一个委托回调。

类SubscriberCallback:

#region using statements

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

#endregion

namespace BlazorChat
{

    #region class SubscriberCallback
    /// <summary>
    /// This class is used to register a subscriber with the ChatService
    /// </summary>
    public class SubscriberCallback
    {

        #region Private Variables
        private string name;
        private Guid id;
        private Callback callback;
        private List<Guid> blockedList;
        #endregion

        #region Constructor
        /// <summary>
        /// Create a new instance of a SubscriberCallback instance
        /// </summary>
        public SubscriberCallback(string name)
        {
            // store the Name
            Name = name;

            // Create the Id
            Id = Guid.NewGuid();

            // create a BlockedList
            BlockedList = new List<Guid>();
        }
        #endregion

        #region Methods

            #region ToString()
            /// <summary>
            /// This method is used to return the Name of the Subscriber when ToString is called.
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                // return the Name when ToString is called
                return this.Name;
            }
            #endregion

        #endregion

        #region Properties

            #region BlockedList
            /// <summary>
            /// This property gets or sets the value for 'BlockedList'.
            /// </summary>
            public List<Guid> BlockedList
            {
                get { return blockedList; }
                set { blockedList = value; }
            }
            #endregion

            #region Callback
            /// <summary>
            /// This property gets or sets the value for 'Callback'.
            /// </summary>
            public Callback Callback
            {
                get { return callback; }
                set { callback = value; }
            }
            #endregion

            #region HasBlockedList
            /// <summary>
            /// This property returns true if this object has a 'BlockedList'.
            /// </summary>
            public bool HasBlockedList
            {
                get
                {
                    // initial value
                    bool hasBlockedList = (this.BlockedList != null);

                    // return value
                    return hasBlockedList;
                }
            }
            #endregion

            #region HasCallback
            /// <summary>
            /// This property returns true if this object has a 'Callback'.
            /// </summary>
            public bool HasCallback
            {
                get
                {
                    // initial value
                    bool hasCallback = (this.Callback != null);

                    // return value
                    return hasCallback;
                }
            }
            #endregion

            #region HasName
            /// <summary>
            /// This property returns true if the 'Name' exists.
            /// </summary>
            public bool HasName
            {
                get
                {
                    // initial value
                    bool hasName = (!String.IsNullOrEmpty(this.Name));

                    // return value
                    return hasName;
                }
            }
            #endregion

            #region Id
            /// <summary>
            /// This property gets or sets the value for 'Id'.
            /// </summary>
            public Guid Id
            {
                get { return id; }
                set { id = value; }
            }
            #endregion

            #region Name
            /// <summary>
            /// This property gets or sets the value for 'Name'.
            /// </summary>
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            #endregion

        #endregion

    }
    #endregion

}

委托类回调:

类回调:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorChat
{
    /// <summary>
    /// This delegate is used by the SubscriberService to send messages to any subscribers
    /// </summary>    
    /// <returns></returns>
    public delegate void Callback(SubscriberMessage message);
}

每个用户连接并注册服务器:

SubscriberCallback callback = new SubscriberCallback(SubscriberName);
callback.Callback = Listen;
callback.Name = SubscriberName;

// Get a message back
SubscriberMessage message = SubscriberService.Subscribe(callback);

Listen方法是SubscriberService回调的方法:

public void Listen(SubscriberMessage message)
{
    // if the message exists, same as message != null
    if (NullHelper.Exists(message))
    {
        // if the message is a SystemMessage
        if (message.IsSystemMessage)
        {   
            // Get the Names again
            this.Names = SubscriberService.GetSubscriberNames();
         }
         else
         {  
             // Get the Messages
             this.Messages = SubscriberService.GetBroadcastMessages(this.Id, DisplayMessagesCount);          
         }

        // Update the UI
        Refresh();
    }
}

我将发布的最后一件事是订阅者消息,我用它向订阅者发送消息:

#region using statements

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BlazorChat.Enumerations;

#endregion

namespace BlazorChat
{

    #region class SubscriberMessage
    /// <summary>
    /// This class is used to send information between components / pages.
    /// </summary>
    public class SubscriberMessage
    {

        #region Private Variables
        private string text;
        private Guid fromId;
        private Guid toId;
        private string fromName;
        private string toName;
        private object data;
        private string valid;
        private DateTime sent;
        private bool isSystemMessage;
        private string invalidReason;
        private BubbleColorEnum bubbleColor;
        private string imageUrl;
        private bool isPrivate;
        private DateTime sentTime;
        #endregion

        #region Methods

            #region SetImageUrl()
            /// <summary>
            /// This method Set Image Url
            /// </summary>
            public void SetImageUrl()
            {
                // as long as the BubbleColor is set this will work
                if (BubbleColor != BubbleColorEnum.NotSet)
                {  
                    // Set the ImageUrl
                    ImageUrl = "../Images/Bubbles/" + BubbleColor.ToString() + ".png";
                }
            }
            #endregion

        #endregion

        #region Properties

            #region BubbleColor
            /// <summary>
            /// This property gets or sets the value for 'BubbleColor'.
            /// </summary>
            public BubbleColorEnum BubbleColor
            {
                get { return bubbleColor; }
                set 
                {
                    // set the bubbleColor
                    bubbleColor = value;

                    // Set the ImageUrl
                    SetImageUrl();
                }
            }
            #endregion

            #region Data
            /// <summary>
            /// This property gets or sets the value for 'Data'.
            /// </summary>
            public object Data
            {
                get { return data; }
                set { data = value; }
            }
            #endregion

            #region FromId
            /// <summary>
            /// This property gets or sets the value for 'FromId'.
            /// </summary>
            public Guid FromId
            {
                get { return fromId; }
                set { fromId = value; }
            }
            #endregion

            #region FromName
            /// <summary>
            /// This property gets or sets the value for 'FromName'.
            /// </summary>
            public string FromName
            {
                get { return fromName; }
                set { fromName = value; }
            }
            #endregion

            #region HasText
            /// <summary>
            /// This property returns true if the 'Text' exists.
            /// </summary>
            public bool HasText
            {
                get
                {
                    // initial value
                    bool hasText = (!String.IsNullOrEmpty(this.Text));

                    // return value
                    return hasText;
                }
            }
            #endregion

            #region ImageUrl
            /// <summary>
            /// This property gets or sets the value for 'ImageUrl'.
            /// </summary>
            public string ImageUrl
            {
                get { return imageUrl; }
                set { imageUrl = value; }
            }
            #endregion

            #region InvalidReason
            /// <summary>
            /// This property gets or sets the value for 'InvalidReason'.
            /// </summary>
            public string InvalidReason
            {
                get { return invalidReason; }
                set { invalidReason = value; }
            }
            #endregion

            #region IsPrivate
            /// <summary>
            /// This property gets or sets the value for 'IsPrivate'.
            /// </summary>
            public bool IsPrivate
            {
                get { return isPrivate; }
                set { isPrivate = value; }
            }
            #endregion

            #region IsSystemMessage
            /// <summary>
            /// This property gets or sets the value for 'IsSystemMessage'.
            /// </summary>
            public bool IsSystemMessage
            {
                get { return isSystemMessage; }
                set { isSystemMessage = value; }
            }
            #endregion

            #region Sent
            /// <summary>
            /// This property gets or sets the value for 'Sent'.
            /// </summary>
            public DateTime Sent
            {
                get { return sent; }
                set { sent = value; }
            }
            #endregion

            #region SentTime
            /// <summary>
            /// This property gets or sets the value for 'SentTime'.
            /// </summary>
            public DateTime SentTime
            {
                get { return sentTime; }
                set { sentTime = value; }
            }
            #endregion

            #region Text
            /// <summary>
            /// This property gets or sets the value for 'Text'.
            /// </summary>
            public string Text
            {
                get { return text; }
                set { text = value; }
            }
            #endregion

            #region ToId
            /// <summary>
            /// This property gets or sets the value for 'ToId'.
            /// </summary>
            public Guid ToId
            {
                get { return toId; }
                set { toId = value; }
            }
            #endregion

            #region ToName
            /// <summary>
            /// This property gets or sets the value for 'ToName'.
            /// </summary>
            public string ToName
            {
                get { return toName; }
                set { toName = value; }
            }
            #endregion

            #region Valid
            /// <summary>
            /// This property gets or sets the value for 'Valid'.
            /// </summary>
            public string Valid
            {
                get { return valid; }
                set { valid = value; }
            }
            #endregion

        #endregion

    }
    #endregion

}

该网站也是直播的,但目前还没有多少人报名:

https://blazorchat.com