一个简单的状态机,使用C#中的Static类通过事件通知其他订阅者

Pre*_*zel 4 c# events static class state-machine

我一直在尝试为我的应用程序编写一个简单的静态类状态机,以便在系统状态发生变化时通知其他控件和代码.我想我几乎拥有它,但我遇到了一个小问题,我不知道如何解决.

这是代码:

// An enum denoting the 3 States
public enum Status { Error = -1, Working, Ready }

// The main state change class
public static class Sys
{
    // system status
    private static Status state;

    // delegate and event
    public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);
    public static event StateChangeHandler OnStateChange;

    public static Status State
    {
        get { return state; }
        set
        {
            SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
            state = value;
            OnStateChange(this, sysInfo);
        }
    }
}

/// <summary>Contains previous and current state info</summary>
public class SysInfoEventArgs : EventArgs
{
    public readonly Status oldState;
    public readonly Status newState;
    public SysInfoEventArgs(Status oldState, Status newState)
    {
        this.oldState = oldState;
        this.newState = newState;
    }
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是这一行:

 OnStateChange(this, sysInfo);
Run Code Online (Sandbox Code Playgroud)

具体来说,"this"这个词是非法的.我理解为什么:"this"应该引用一个实例化对象(不是静态类)的self.

我宁愿为我的状态机安装一个静态类,而不是一个可以实例化多个副本的静态类.(并不是说它会是一件坏事,但我觉得它使代码更清晰,有一个静态类.)

那我该怎么做呢?

更新:

作为后续行动,我选择Jon Skeet作为正确的答案,因为问题更多的是关于我采取的方法,而不是我所遇到的技术故障.虽然,下面几乎所有其他答案都解决了我正在处理的技术故障.

奇怪的是,当我和我的同事一起审阅我写的应用程序时,她指出程序应该跟踪服务器连接的状态以及正在完成的工作的状态.(是的,弗吉尼亚州,这意味着我需要2台状态机... Ergo,从上面的代码中删除所有"静态"关键字并使其成为常规类是智能方法.)

再次感谢大家!

Jon*_*eet 14

你为什么想要一个静态类?它是一个状态机 - 它有状态 - 自然建议使用非静态类.如果你真的想要,你总是可以有一个静态变量引用它的单个实例.

基本上,你的直觉在我看来是不正确的 - 拥有一个普通的类会使代码比静态的更干净.静态类应该很少有任何状态 - 可能是缓存(尽管甚至可疑),或用于诊断目的的计数器等.尝试用对象而不是来思考.拥有两个独立的状态机,具有不同的当前状态和可能不同的事件处理程序是否有意义?很容易想象就是这种情况 - 这意味着很容易为测试等创建新实例(它还允许独立测试并行运行.)因此,在机器实例中具有状态是很自然的.

有些人认为应该没有静态方法,没有静态类等.我认为这有点远,但你应该总是至少考虑引入静态的可测试性影响.


Ree*_*sey 6

当您在静态范围内工作时,不能使用"this",例如静态类或静态方法.

你有两个选择.您可以传递null"sys"参数.实际上,在静态类的情况下,此参数实际上没用,因为"sender"始终是静态类.

或者,您可能需要考虑使您的状态通知符成为单例.这将允许您拥有非静态类的单个实例.如果未来的需求发生变化,这确实具有使得更容易转换到非静态实现的一个优点.


此外,在发起此活动之前,您确实应该检查以确保有订阅者.不这样做可能会导致问题:

public static Status State
{
    get { return state; }
    set
    {
        SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
        state = value;
        var handler = OnStateChange;
        if (handler != null)
            handler(null, sysInfo);
    }
}
Run Code Online (Sandbox Code Playgroud)