简体   繁体   English

C# 状态模式和事件

[英]C# State pattern and events

In C#, events can only be fired by the owning class through protected virtual methods such as OnClick, OnExit, etc... What I'm trying to do is implementing GOF State Pattern for some of my complex classes.在 C# 中,事件只能由所属类通过受保护的虚拟方法(如 OnClick、OnExit 等)触发……我想做的是为我的一些复杂类实现 GOF 状态模式。 Everything worked great so far except that I can't find a way to fire an event of the owning class from my state class.到目前为止,一切都很好,只是我找不到从我的状态类中触发拥有类的事件的方法。

For example, my button has two states (up and down) and the DownState class will check for user input and if necessary, fire the button's Click event.例如,我的按钮有两种状态(向上和向下),DownState 类将检查用户输入,并在必要时触发按钮的 Click 事件。

public class Button
{
    public Button()
    {
        State = new ButtonStateNormal(this);
    }

    public event EventHandler<MouseEventArgs> Click;
    public ButtonState State { get; set; }

    protected virtual void OnClick(MouseEventArgs e)
    {
        if (Click != null)
            Click(this, e);
    }
}

public class ButtonStateNormal : ButtonState
{
    Button button;
    public ButtonStateNormal(Button button)
    {
        this.button = button;
    }

    public override void CheckForInput()
    {
        //...
        //Check for user input and change the state
        //...
        button.State = new ButtonStateDown(button);
    }
}

public class ButtonStateDown : ButtonState
{
    Button button;
    public ButtonStateDown(Button button)
    {
        this.button = button;
    }

    public override void CheckForInput()
    {
        //...
        //Check for user input, fire the event of the button and change the state
        //...
        button.OnClick(new MouseEventArgs(mouse.X, mouse.Y)); //I want to do this, obviously it won't work this way
        button.State = new ButtonStateNormal(button);
    }
}

How can I do that?我怎样才能做到这一点?

Set up an event or delegate on your ButtonState class, that your buttons thus can call.ButtonState类上设置事件或委托,以便您的按钮可以调用。 Change your automatic State property in Button to one with a backing store that hooks and unhooks the this event or delegate whenever the state is changed.Button自动State属性更改为一个后备存储,该存储在状态更改时挂钩和取消挂钩此事件或委托。

public class Button
{
    public Button()
    {
        State = new ButtonStateNormal(this);
    }
    private ButtonState _state;
    public event EventHandler<MouseEventArgs> Click;
    public ButtonState State
    {
        protected get
        {
            return _state;
        }
        set
        {
            if (_state == value)
                return;
            if (_state != null)
                _state.Click -= OnClick;
            if (value != null)
                value.Click += OnClick;

            _state = value;

        }
    }

    protected virtual void OnClick(MouseEventArgs e)
    {
        if (Click != null)
            Click(this, e);
    }

    public void CheckForInput(){
        State.CheckForInput();
    }
}

public abstract class ButtonState
{
    public abstract void CheckForInput();
    public ClickDelegate Click;
    public delegate void ClickDelegate(MouseEventArgs a);
}

And then you can do this in your concrete State classes然后您可以在具体的 State 类中执行此操作

public class ButtonStateDown : ButtonState
{
    Button button;
    public ButtonStateDown(Button button)
    {
        this.button = button;
    }

    public void CheckForInput()
    {
        //...
        //Check for user input, fire the event of the button and change the state
        //...
        if(Click != null)
            Click(new MouseEventArgs(mouse.X, mouse.Y))
        button.State = new ButtonStateNormal(button);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM