C# 带对象键的字典

C# 带对象键的字典,c#,.net,dictionary,C#,.net,Dictionary,我正在努力使用一个特定的字典来改变一个对象的状态 我的想法是,我有一个类进程,它是每次用户提交要处理的内容时创建的。进程具有ID、一些其他信息和当前状态。可能的CurrentState在StateEnum类中定义,包含“挂起、处理、完成、错误”等状态。 之后,用户可以执行一些任务/命令——每个任务也被定义为一个类,并包含进程ID和执行方法ID,从而更改对象的状态。这些任务从接口ITask继承 问题是,我需要某种状态机,它将验证是否可以使用任务“ResumeTask”从状态“Pending”移动到

我正在努力使用一个特定的字典来改变一个对象的状态

我的想法是,我有一个类进程,它是每次用户提交要处理的内容时创建的。进程具有ID、一些其他信息和当前状态。可能的CurrentState在StateEnum类中定义,包含“挂起、处理、完成、错误”等状态。 之后,用户可以执行一些任务/命令——每个任务也被定义为一个类,并包含进程ID和执行方法ID,从而更改对象的状态。这些任务从接口ITask继承

问题是,我需要某种状态机,它将验证是否可以使用任务“ResumeTask”从状态“Pending”移动到状态“Processing”。为了进行此验证,我使用字典创建了类状态,并且每次创建进程时都会创建其对象

问题是,这本词典不能正常使用。让我用一些注释展示代码(我创建了简单的控制台应用程序只是为了演示问题),并解释发生了什么:

ITask接口

public interface ITask
{

    int IntParam1 { get; set; }

    void Execute(Process proc);

}
ResumeTask类(我还有暂停任务和其他任务)

过程类

class ResumeTask : ITask
{

    int intParam1;
    public int IntParam1
    {
        get { return intParam1; }
        set { intParam1 = value; }
    }


    public void Execute(Process proc)
    {
        ResumeTask resume = new ResumeTask();
        proc.ChangeState(resume);

        //code below not working - is there a way how to make this 
        //work instead of creating new empty class above?
        //proc.ChangeState(this);
    }

    public override int GetHashCode()
    {
        return 17 + 31 * intParam1.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        ResumeTask other = obj as ResumeTask;
        return other != null && this.intParam1 == other.intParam1;
    }


}
public class Process
{

    State stat;


    private int processID;
    public int ProcessID
    {
        get { return processID; }
        private set { processID = value; }
    }

    private StateEnum state;
    public StateEnum State
    {
        get { return state; }
        set { state = value; }
    }

    public readonly int userID;
    public int UserID
    {
        get { return userID; }
    }

    public Process(int processID, int userID)
    {
        this.processID = processID;
        this.userID = userID;
        stat = new State();
        this.state = stat.CurrentState;
    }

    public void ChangeState(ITask task)
    {

        this.state = stat.MoveNext(task);

    }

}
class State
{

    private class StateTransition
    {
        public StateEnum State;
        public ITask Task;

        public StateTransition(StateEnum state, ITask task)
        {
            State = state;
            Task = task;
        }

        public override int GetHashCode()
        {
            return 17 + 31 * State.GetHashCode() + 31 * Task.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            StateTransition other = obj as StateTransition;
            return other != null && this.State == other.State && this.Task == other.Task;
        }
    }


    public StateEnum CurrentState;

    Dictionary<StateTransition, StateEnum> transitions;

    ITask pause = new PauseTask();
    ITask resume = new ResumeTask();

    ITask resumenew = new ResumeTask();


    public State()
    {

        CurrentState = StateEnum.Pending;
        transitions = new Dictionary<StateTransition, StateEnum>
        {
            { new StateTransition(StateEnum.Processing, pause), StateEnum.Pending },
            { new StateTransition(StateEnum.Pending, resume), StateEnum.Processing }
        };
    }


    public StateEnum MoveNext(ITask task)
    {
        StateTransition transition = new StateTransition(CurrentState, task);
        StateEnum nextState;
        if (!transitions.TryGetValue(transition, out nextState))
        {
            return StateEnum.Error;
        }
        else
        {
            return nextState;
        }
    }

}
class Program
{
    static void Main(string[] args)
    {

        Process proc = new Process(1, 20);

        ResumeTask resumetask = new ResumeTask();
        resumetask.IntParam1 = 1;
        resumetask.Execute(proc);

        Console.WriteLine(Convert.ToString(proc.ProcessState));
        Console.ReadLine();


    }
}
国家级

class ResumeTask : ITask
{

    int intParam1;
    public int IntParam1
    {
        get { return intParam1; }
        set { intParam1 = value; }
    }


    public void Execute(Process proc)
    {
        ResumeTask resume = new ResumeTask();
        proc.ChangeState(resume);

        //code below not working - is there a way how to make this 
        //work instead of creating new empty class above?
        //proc.ChangeState(this);
    }

    public override int GetHashCode()
    {
        return 17 + 31 * intParam1.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        ResumeTask other = obj as ResumeTask;
        return other != null && this.intParam1 == other.intParam1;
    }


}
public class Process
{

    State stat;


    private int processID;
    public int ProcessID
    {
        get { return processID; }
        private set { processID = value; }
    }

    private StateEnum state;
    public StateEnum State
    {
        get { return state; }
        set { state = value; }
    }

    public readonly int userID;
    public int UserID
    {
        get { return userID; }
    }

    public Process(int processID, int userID)
    {
        this.processID = processID;
        this.userID = userID;
        stat = new State();
        this.state = stat.CurrentState;
    }

    public void ChangeState(ITask task)
    {

        this.state = stat.MoveNext(task);

    }

}
class State
{

    private class StateTransition
    {
        public StateEnum State;
        public ITask Task;

        public StateTransition(StateEnum state, ITask task)
        {
            State = state;
            Task = task;
        }

        public override int GetHashCode()
        {
            return 17 + 31 * State.GetHashCode() + 31 * Task.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            StateTransition other = obj as StateTransition;
            return other != null && this.State == other.State && this.Task == other.Task;
        }
    }


    public StateEnum CurrentState;

    Dictionary<StateTransition, StateEnum> transitions;

    ITask pause = new PauseTask();
    ITask resume = new ResumeTask();

    ITask resumenew = new ResumeTask();


    public State()
    {

        CurrentState = StateEnum.Pending;
        transitions = new Dictionary<StateTransition, StateEnum>
        {
            { new StateTransition(StateEnum.Processing, pause), StateEnum.Pending },
            { new StateTransition(StateEnum.Pending, resume), StateEnum.Processing }
        };
    }


    public StateEnum MoveNext(ITask task)
    {
        StateTransition transition = new StateTransition(CurrentState, task);
        StateEnum nextState;
        if (!transitions.TryGetValue(transition, out nextState))
        {
            return StateEnum.Error;
        }
        else
        {
            return nextState;
        }
    }

}
class Program
{
    static void Main(string[] args)
    {

        Process proc = new Process(1, 20);

        ResumeTask resumetask = new ResumeTask();
        resumetask.IntParam1 = 1;
        resumetask.Execute(proc);

        Console.WriteLine(Convert.ToString(proc.ProcessState));
        Console.ReadLine();


    }
}
程序类

class ResumeTask : ITask
{

    int intParam1;
    public int IntParam1
    {
        get { return intParam1; }
        set { intParam1 = value; }
    }


    public void Execute(Process proc)
    {
        ResumeTask resume = new ResumeTask();
        proc.ChangeState(resume);

        //code below not working - is there a way how to make this 
        //work instead of creating new empty class above?
        //proc.ChangeState(this);
    }

    public override int GetHashCode()
    {
        return 17 + 31 * intParam1.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        ResumeTask other = obj as ResumeTask;
        return other != null && this.intParam1 == other.intParam1;
    }


}
public class Process
{

    State stat;


    private int processID;
    public int ProcessID
    {
        get { return processID; }
        private set { processID = value; }
    }

    private StateEnum state;
    public StateEnum State
    {
        get { return state; }
        set { state = value; }
    }

    public readonly int userID;
    public int UserID
    {
        get { return userID; }
    }

    public Process(int processID, int userID)
    {
        this.processID = processID;
        this.userID = userID;
        stat = new State();
        this.state = stat.CurrentState;
    }

    public void ChangeState(ITask task)
    {

        this.state = stat.MoveNext(task);

    }

}
class State
{

    private class StateTransition
    {
        public StateEnum State;
        public ITask Task;

        public StateTransition(StateEnum state, ITask task)
        {
            State = state;
            Task = task;
        }

        public override int GetHashCode()
        {
            return 17 + 31 * State.GetHashCode() + 31 * Task.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            StateTransition other = obj as StateTransition;
            return other != null && this.State == other.State && this.Task == other.Task;
        }
    }


    public StateEnum CurrentState;

    Dictionary<StateTransition, StateEnum> transitions;

    ITask pause = new PauseTask();
    ITask resume = new ResumeTask();

    ITask resumenew = new ResumeTask();


    public State()
    {

        CurrentState = StateEnum.Pending;
        transitions = new Dictionary<StateTransition, StateEnum>
        {
            { new StateTransition(StateEnum.Processing, pause), StateEnum.Pending },
            { new StateTransition(StateEnum.Pending, resume), StateEnum.Processing }
        };
    }


    public StateEnum MoveNext(ITask task)
    {
        StateTransition transition = new StateTransition(CurrentState, task);
        StateEnum nextState;
        if (!transitions.TryGetValue(transition, out nextState))
        {
            return StateEnum.Error;
        }
        else
        {
            return nextState;
        }
    }

}
class Program
{
    static void Main(string[] args)
    {

        Process proc = new Process(1, 20);

        ResumeTask resumetask = new ResumeTask();
        resumetask.IntParam1 = 1;
        resumetask.Execute(proc);

        Console.WriteLine(Convert.ToString(proc.ProcessState));
        Console.ReadLine();


    }
}
让我们快速浏览一些要点:

  • 在所有任务中,我都覆盖了Equals和GetHashCode方法,因为我知道,如果我想在字典中使用object,就必须像这样做
  • 如果您注意到execute方法-问题是,当我之前在一个更简单的示例上测试它时,我必须传递不带任何值的新对象,以便获得一些成功的结果-可能这是因为在dictionary中,我有一个空类,但我传递的类设置为intParam1,并尝试比较它们
  • 在Process类中,我只需创建新的状态对象并从中获取CurrentState。此外,MoveNext方法只需在Task中传递来自Execute()方法的输入参数
  • 在国家级,有一个最大的问题(我认为)。正如您所看到的,我必须创建另一种类型“StateTransformation”(这是从StackOverflow上的状态机示例中借用的),因为在实际应用程序中,有更多的任务可以在特定的状态上执行——为了在字典中有唯一的键,我必须这样做。 基本上,我创建了类型,再次覆盖Equald和GetHashCode,然后创建dictionary,其中StateTransformation作为一个键。我不得不创建任务的空对象(暂停、恢复),以便将它们放入字典中——我不确定这是否是正确的方法,但它在某种程度上起到了作用。 之后,我尝试为键找到一个值,该值由进程和任务中的CurrentState组成,我在前面的Execute()方法中传递了该值。但结果总是“错误”
  • 我尝试了几种方法-我尝试创建了两个简单的词典:

    转换

    可用的任务

    它工作得很好-我在MoveNext方法中检查了它们,并且能够进行有效的移动-问题是,使用这种方法,我无法创建场景,在这种场景中,我需要为一个状态提供多个任务

  • 我还试着试验《宣言》
  • StateTransformation=新的StateTransformation(当前状态,任务)

    在State类中的MoveNext方法中——例如,如果我将对象“resume”(之前创建该对象是为了将其添加到字典中)而不是“task”参数,那么它是有效的——因为我基本上是在比较两个相同的对象。但是,正如你们所看到的,我也试图定义对象

    ITask resumenew=新的ResumeTask()

    并再次传递它,而不是“任务”参数-它不工作

    总而言之,这是一个糟糕的方法,还是我在某个地方犯了一些我不知道的小错误? 我希望这个问题不要太混乱-如果有任何问题,我可以编辑它或在评论中回答。谢谢你的帮助


    编辑: 如果我将其余部分保持原样,只需像这样更改State类:

    class State
    {
    
    
    
    
        public StateEnum CurrentState;
    
        Dictionary<ITask, StateEnum> transitions;
    
        ITask pause = new PauseTask();
        ITask resume = new ResumeTask();
    
        public State()
        {
    
            CurrentState = StateEnum.Pending;
            transitions = new Dictionary<ITask, StateEnum>
            {
                {pause, StateEnum.Pending },
                {resume, StateEnum.Processing }
            };
        }
    
    
        public StateEnum MoveNext(ITask task)
        {
            StateEnum nextState;
            if (!transitions.TryGetValue(task, out nextState))
            {
                return StateEnum.Error;
            }
            else
            {
                return nextState;
            }
        }
    
    }
    
    类状态
    {
    公共状态枚举当前状态;
    词典转换;
    ITask pause=新的PauseTask();
    ITask resume=新的ResumeTask();
    公共国家()
    {
    CurrentState=StateEnum.Pending;
    转换=新字典
    {
    {暂停,StateEnum.Pending},
    {resume,StateEnum.Processing}
    };
    }
    公共状态枚举移动下一步(ITask任务)
    {
    statenum nextState;
    if(!transitions.TryGetValue(任务,out nextState))
    {
    返回StateEnum.Error;
    }
    其他的
    {
    返回下一状态;
    }
    }
    }
    
    它正在工作-如果状态为StateEnum.Pending,并且我在MoveNext()方法中传递task ResumeTask ResumeTask=new ResumeTask(),它将返回我StateEnum.Processing,这是正确的

    所以“简单”对象键字典正在工作,但是当我将该对象封装到另一个对象中时,尽管再次重写Equals和GetHashCode,我还是无法获得匹配项(该实现显示在主post-State类中)

    问题是,如果我基本上是传递同一类的对象,为什么我不能得到匹配


    EDIT2:

    这对于我所需要的目的来说太复杂了。我尝试了使用
    List
    的不同方法,因为创建字典后我不需要更改它,而且List对于更多值使用相同的键没有问题。到目前为止,它正在发挥作用


    如果需要,我可以发布最终的代码。

    在其他情况下缩小您的问题这对我来说是“太宽泛的问题”,我不知道您的确切意思,但基本上我不明白,为什么要使用“简单”对象键字典