C# 请帮助我以正确的方式编写此事件 原始问题

C# 请帮助我以正确的方式编写此事件 原始问题,c#,events,conventions,C#,Events,Conventions,我至少读过十几篇关于事件的文章和线索,并且已经弄明白了基本的想法,但是我对如何正确地做这件事有点困惑™. 似乎至少有两种编写事件的常用方法,一种比另一种更受推荐 我看到了很多资料,作者跳过了部分过程,假设出于某种原因,你会知道这一点。还有很多教程,比如“MyEventExample”和“SomeProcessGoesher”,这使得我们很难从整体上理解这个例子。许多例子在教你如何做某件事的过程中经历了所有的麻烦,但最后只是说你在现实中当然永远不会做那件事——但它们并没有提供你做这件事的方式 最后

我至少读过十几篇关于事件的文章和线索,并且已经弄明白了基本的想法,但是我对如何正确地做这件事有点困惑™. 似乎至少有两种编写事件的常用方法,一种比另一种更受推荐

我看到了很多资料,作者跳过了部分过程,假设出于某种原因,你会知道这一点。还有很多教程,比如“MyEventExample”和“SomeProcessGoesher”,这使得我们很难从整体上理解这个例子。许多例子在教你如何做某件事的过程中经历了所有的麻烦,但最后只是说你在现实中当然永远不会做那件事——但它们并没有提供你做这件事的方式

最后,使用事件的场景的每个组件的命名约定似乎无处不在。我很难弄清楚某些概念在哪里被应用,因为每个人对它的每个部分都有不同的名称

这就是我想要的:我在游戏中有一个简单的情况,可以利用事件。我希望有人能进来写一篇事件连线,展示推荐的方法以及最常见的命名和结构约定。我知道要求为我编写代码的形式很糟糕,但我真的在寻找编写代码的方法,这样我就可以自信地开始为自己编写代码了

请忽略这是否是一个好的游戏设计,甚至它是否是一个事件的适当情况。我只是对如何正确编写事件内容感兴趣,这是我的示例空间


//In my game I have a number of entities which can 'talk' to the player. 
//An NPC can greet them, a zone might 'greet' them by displaying "Cityville" 
//when they enter it, their inventory might tell them they're out of space, 
//and so on. Everything would pass a Message object to a Messenger object, 
//which would then deliver the messages as it saw fit.

public class Messenger
{
    private Queue<Message> _messages = new Queue<Message>();;
    private Stack<Message> _archive = new Stack<Message>();;

    public IEnumerable<Message> Messages { get { return _messages.AsEnumerable(); } }
    public IEnumerable<Message> Archive { get { return _archive.AsEnumerable(); } }

    public void Add(Message message)
    {
        _messages.Enqueue(message);
    }
    public void Deliver()
    {
        Message msg = _messages.Dequeue();
        _archive.Push(msg);

        //Here's where I'd broadcast to any subsystem listening 
        //that the message was delivered 
        //Event args should be (_archive.Peek(), DateTime.Now);
            
    }
        
    public event MessageDeliveryEvent Delivery;
    protected virtual void OnDelivery(MessageHandlerDeliveryEventArgs e)
    {
        if (this.Delivery != null) { this.Delivery(this, e); }
    }
}

//Okay, here's my delegate declared outside any class. One tutorial suggested 
//putting it in the same file as the event arguments class so it would be 
//easier to find, which sounds reasonable to me, but I dunno.

public delegate void MessageDeliveryEvent(object sender, MessageHandlerDeliveryEventArgs e);

//I've seen examples where they don't even write an event arguments class. 
//I think you could probably just pass the same stuff directly, but the 
//separate class sounds like a good idea, more flexible if things change.

public class MessageHandlerDeliveryEventArgs : EventArgs
{
    private readonly Message _message;
    private readonly DateTime _delivered;

    public MessageHandlerDeliveryEventArgs(Message message, DateTime delivered)
    {
        _message = message;
        _delivered = delivered;
    }

    public Message Message { get { return _message; } }
    public DateTime DeliveryDateTime { get { return _delivered; } }
}

//So in the UI layer I'd have things like a ChatBox which would be a
//scrolling list of everything said to the player. There would also be a 
//GeneralInfoBox control that displayed things like what zone you just 
//entered, or that your inventory is full. Both would listen to the 
//Messenger object for a delivery event, and then check the Message object 
//associated with that event to see if they needed to handle the display 
//of that message.

public class ChatBox
{
    //OMG there's a new message, lemme see if I should display it
    private void TheThingThatListensToMessengerEvents(Message message, DateTime datetime)
    {
        if Message.Type == MessageType.Chat { Print(datetime.ToString() + ": " + message.Text); }
    }
    public string Print(string text) {}
}
public class GeneralInfoBox
{
    //OMG there's a new message, lemme see if I should display it
    private void TheThingThatListensToMessengerEvents(Message message)
    {
        if Message.Type == MessageType.General { Print(message.Text); }
    }
    public string Print(string text) {}
}


//在我的游戏中,我有许多实体可以与玩家“对话”。
//NPC可以问候他们,区域可以通过显示“Cityville”来“问候”他们
//当他们进入时,他们的库存可能会告诉他们空间不足,
//等等。一切都会将消息对象传递给Messenger对象,
//然后,它将按照自己认为合适的方式传递信息。
公务舱信使
{
专用队列_messages=new Queue();;
私有堆栈_archive=新堆栈();;
公共IEnumerable消息{get{return_Messages.AsEnumerable();}
公共IEnumerable存档{get{return _Archive.AsEnumerable();}}
公共无效添加(消息)
{
_消息。排队(消息);
}
公共图书馆
{
Message msg=_messages.Dequeue();
_存档推送(msg);
//这是我向任何正在收听的子系统广播的地方
//消息已经传递了
//事件参数应该是(_archive.Peek(),DateTime.Now);
}
公共事件消息传递事件传递;
受保护的虚拟void OnDelivery(MessageHandlerDeliveryEventArgs e)
{
如果(this.Delivery!=null){this.Delivery(this,e);}
}
}
//好的,这是我的委托在任何类之外声明的。一个教程建议
//将它与事件参数类放在同一个文件中
//更容易找到,这听起来很合理,但我不知道。
公共委托void MessageDeliveryEvent(对象发送者,MessageHandlerDeliveryEventArgs e);
//我见过一些例子,其中他们甚至没有编写事件参数类。
//我想你可以直接传递同样的东西,但是
//单独上课听起来是个好主意,如果情况发生变化,会更加灵活。
公共类MessageHandlerDeliveryEventArgs:EventArgs
{
专用只读消息\u消息;
私有只读日期时间(已交付);
public MessageHandlerDeliveryEventArgs(消息消息、日期时间已送达)
{
_消息=消息;
_交付=交付;
}
公共消息消息{get{return_Message;}}
public DateTime DeliveryDateTime{get{return\u delivered;}
}
//因此,在UI层中,我会有一个聊天室之类的东西,它是一个
//滚动列表,列出所有对玩家说的话。还将有一个
//GeneralInfo框控件,该控件显示的内容包括
//输入,或者您的库存已满。两人都会听音乐
//用于传递事件的Messenger对象,然后检查Message对象
//与该事件关联,以查看他们是否需要处理显示
//这一信息的重要性。
公共类聊天室
{
//天哪,有新消息,让我看看是否应该显示它
private void列出的ThingThingthat事件(消息消息、日期时间、日期时间)
{
如果Message.Type==MessageType.Chat{Print(datetime.ToString()+“:”+Message.Text);}
}
公共字符串打印(字符串文本){}
}
公共类通用信息框
{
//天哪,有新消息,让我看看是否应该显示它
private void Thingthat ListentHomesenger事件(消息消息)
{
如果Message.Type==MessageType.General{Print(Message.Text);}
}
公共字符串打印(字符串文本){}
}
如果我能澄清什么,请告诉我。如果有一个非常好的教程我显然错过了,请随时告诉我。提前谢谢


我从线上取了什么 这是我的例子,里面有一些事件。也许它会帮助其他像我一样思考的人(上帝保佑他们)想象它


public class MessageHandler
{
    private Queue<Message> _messages = new Queue<Message>();
    private Stack<Message> _archive = new Stack<Message>();

    public MessageHandler() { }

    public IEnumerable<Message> Messages { get { return _messages.AsEnumerable(); } }
    public IEnumerable<Message> Archive { get { return _archive.AsEnumerable(); } }

    public void Add(Message message)
    {
        _messages.Enqueue(message);
    }
    public void Deliver()
    {
        Message msg = _messages.Dequeue();
        _archive.Push(msg);

        //Call the method which broadcasts the event
        OnDelivery(new MessageDeliveryEventArgs(_archive.Peek(), DateTime.Now));
    }

    //The event
    public event EventHandler<MessageDeliveryEventArgs> Delivery;

    //The method which broadcasts the event
    protected virtual void OnDelivery(MessageDeliveryEventArgs messageDeliveryEventArgs)
    {
        EventHandler<MessageDeliveryEventArgs> handler = Delivery;
        if (handler != null) { handler(this, messageDeliveryEventArgs); }
    }
}

//The event arguments class for the event of interest. Carries information about this kind of event
public class MessageDeliveryEventArgs : EventArgs
{
    private readonly Message _message;
    private readonly DateTime _delivered;

    public MessageDeliveryEventArgs(Message message, DateTime delivered)
    {
        _message = message;
        _delivered = delivered;
    }

    public Message Message { get { return _message; } }
    public DateTime DeliveryDateTime { get { return _delivered; } }
}

//A UI control which listens for an event in a Messenger object
public class ChatBox
{
    //Specify the instance of the Messenger class to whose event(s) we plan to subscribe
    public ChatBox(MessageHandler messenger)
    {
        //Subscribe this control's OnDelivery method to the Delivery event of the specified instance of Messenger
        messenger.Delivery += this.OnDelivery;
    }

    //The method which we intend to subscribe to the Delivery event of an instance of Messenger
    private void OnDelivery(object sender, MessageDeliveryEventArgs e)
    {
        if (e.Message.Format == MessageFormat.Local)
        {
            Print(String.Format("{0}: {1}", e.DeliveryDateTime, e.Message.Text));
        }
    }
    private void Print(string text) { }
}

公共类MessageHandler
{
专用队列_messages=新队列();
私有堆栈_archive=新堆栈();
public MessageHandler(){}
公共IEnumerable消息{get{return_Messages.AsEnumerable();}
公共IEnumerable存档{get{return _Archive.AsEnumerable();}}
公共无效添加(消息)
{
_消息。排队(消息);
}
公共图书馆
{
Message msg=_messages.Dequeue();
_存档推送(msg);
//调用广播事件的方法
OnDelivery(新的MessageDeliveryEventArgs(_archive.Peek(),DateTime.Now));
}
//事件
公共事件处理程序交付;
//广播的方法
public class ChatBox
{
    public ChatBox(Messenger messenger)
    {
        messenger.Delivery += OnMessageDelivery;
    }

    private void OnMessageDelivery(object sender, MessageHandlerDeliveryEventArgs e)
    {
        if(e.Message.Type == MessageType.Chat)
        {
            Print(String.Format("{0}: {1}", e.DateTime, e.Message.Text));
        }
    }
}
public event EventHandler<MessageHandlerDeliveryEventArgs> Delivery;
using System;

namespace ObserverExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var subject = new Subject();
            var observer = new Observer();
            observer.Observe(subject);
            subject.SomeAction();
            Console.ReadLine();
        }
    }  

    public class Subject
    {
        public event EventHandler<TopicEventArgs> TopicHappening;

        public void SomeAction()
        {
            OnTopicHappening(new TopicEventArgs("Hello, observers!"));
        }

        protected virtual void OnTopicHappening(TopicEventArgs topicEventArgs)
        {
            EventHandler<TopicEventArgs> handler = TopicHappening;

            if (handler != null)
                handler(this, topicEventArgs);
        }
    }

    public class TopicEventArgs : EventArgs
    {
        public TopicEventArgs(string message)
        {
            Message = message;
        }

        public string Message { get; private set; }
    }

    public class Observer
    {
        public void Observe(Subject subject)
        {
            subject.TopicHappening += subject_TopicHappening;
        }

        void subject_TopicHappening(object sender, TopicEventArgs e)
        {
            Console.WriteLine(e.Message);
        }
    }
}