从构造函数中提取继承的 class 参数

Extract inherited class argument from constructor

首先很抱歉,如果我使用了一个混乱的术语,我仍在学习很多关于命令模式和 C# 的知识。

我正在尝试使用 C# 在 Unity3D 中实现命令模式,特别是 this implementation 重新适应我的情况。

鉴于 Command.cs and the GameController.cs 脚本,我创建了一个 DoThing class,继承自 Command class,使用以下代码实现:

public class DoThing : Command
{
    public string name;
    public int healthPoints;

    public DoThing(string name, int healthPoints)
    {
        this.name = name;
        this.healthPoints = healthPoints;
    }
}

现在,由于我通过构造函数(namehealthPoints)向命令传递了一些参数,所以我想从另一个脚本中提取这些参数。

我尝试(成功地)将参数传递给下一行中的命令并将命令保存在堆栈中:

var doCommand = new DoThing("asdf", 123);
Stack<Command> listOfCommands = new Stack<Command>();
listOfCommands.Push(doCommand);

我尝试(成功)在手表 window 中检索这些参数 ,在代码执行期间 :

listOfCommands.Peek().name //returns "asdf"

但这在脚本中不起作用,这意味着无法看到参数:

Debug.Log(listOfCommands.Peek().name) //throws error

有没有办法提取参数?

来自 Command pattern 维基:

A command object knows about receiver and invokes a method of the receiver. Values for parameters of the receiver method are stored in the command. The receiver object to execute these methods is also stored in the command object by aggregation. The receiver then does the work when the execute() method in command is called. An invoker object knows how to execute a command, and optionally does bookkeeping about the command execution. The invoker does not know anything about a concrete command, it knows only about the command interface.

因此,如果 DoThing 命令的作用是将消息记录到控制台,它应该如下所示:

public abstract class Command
{
    public abstract void Execute();        
}

public class DoThing : Command
{
    public string name;
    public int healthPoints;

    public DoThing(string name, int healthPoints)
    {
        this.name = name;
        this.healthPoints = healthPoints;
    }
    public override void Execute(){
        Debug.Log(name);
        // whatever else the command does
    }
}

然后你会在命令上调用执行。

由于您的 listOfCommandsCommandStacklistOfCommands.Peek() returns Command 没有 name 变量。您必须检查函数返回的变量类型并在访问变量之前对其进行转换。

Command command = listOfCommands.Peek();
if(command is DoThing)
{
    Debug.Log(((DoThing) command).name);
}

或更紧凑

if(listOfCommands.Peek() is DoThing doThing)
{
    Debug.Log(doThing.name);
}

DoThing doThing = listOfCommands.Peek() as DoThing;
if(doThing != null)
{
    Debug.Log(doThing.name);
}