C# 以命令模式保存系统
我在Unity c#中为员工保存任务时遇到问题。我将它们的任务像命令模式一样实现,并将方法(协同路由)作为任务算法。现在我必须将他们的任务保存到磁盘上,稍后再加载以恢复它们 例如: 任务接口:C# 以命令模式保存系统,c#,unity3d,coroutine,strategy-pattern,saving-data,C#,Unity3d,Coroutine,Strategy Pattern,Saving Data,我在Unity c#中为员工保存任务时遇到问题。我将它们的任务像命令模式一样实现,并将方法(协同路由)作为任务算法。现在我必须将他们的任务保存到磁盘上,稍后再加载以恢复它们 例如: 任务接口: interface IEmployeeTask { IEnumerator PerformTask(); } employee.cs ... public WorkOnTask(IEmployeeTask task) { this.currentTask = task; Star
interface IEmployeeTask
{
IEnumerator PerformTask();
}
employee.cs
...
public WorkOnTask(IEmployeeTask task)
{
this.currentTask = task;
StartCoroutine(task.PerformTask());
}
...
两个任务实现:
class SomeTask1 : IEmployeeTask
{
...
public SomeTask1(int someImportantParameter){...}
public override IEnumerator PerformTask
{
assignedEmployee.GoThere();
yield return new WaitUntil(() => assignedEmployee.ReachedDestination);
assignedEmployee.DoThis();
yield return new WaitUntil(() => assignedEmployee.DidThis);
assignedEmployee.UseParameter(someImportantParameter);
}
}
我无法重新启动这些任务,因此仅通过new或Activator创建任务并分配引用不会有帮助
我可以创建一个save类并将抽象的
TaskSave-IEmployeeTask.GetSave()
和IEmployeeTask.LoadFrom(TaskSave-save)
,为每个任务实现一个类,其中包含一些丑陋的public readonly int-referenceId
,但如果有机会,我可以避免创建所有这些类并保持代码干净,我很想知道这是否可能。在阅读了下面的评论后,我知道了什么:
首先,我应该将更复杂的TAK划分为单个原子步骤的结构,其中包含整个任务中当前步骤的数据。然后保存当前正在运行的任务和步骤以及执行该任务所需的数据
接下来必须有一个工厂,它知道如何使用保存的数据中的当前步骤重新创建任务。为什么不能重新启动任务?您不能再次调用start例程(task.PerformTask())
?我理解你的问题有点困难。这是关于在会话之间将任务保存到磁盘以供使用,还是说在会话期间暂停任务时保存为?我无法重新启动它,因为如果任务中的某项操作要执行两次或更多次,那将是愚蠢的。我必须从外部保存它,然后重新创建tasks状态。再想一想,您的案例是不同的,因为您使用的是委托,您将无法序列化它。也许要构造任务,可以使用反射和外部文件(方法列表)动态运行委托?给你更广阔的竞争环境。即使将委托排队并从外部获取/保存int索引(state)也可以(但这样做会丢失沿途的引用)。一个简单的答案是用单独的对象表示各个步骤,然后将它们序列化为JSON。然后,创建一个可以构建任务的工厂。在我看来,你把这件事复杂化了。您希望保存有关任务的数据,而不是有关其行为的数据。如果您有步骤
对象,那么任务
对象可以是步骤
的数组和指向当前步骤的整数。整个结构是可序列化的,关键是将行为方面与数据驱动方面分开。任务中的任务或步骤仍然可以由协同程序启动,但任务或步骤的状态由数据定义(而不是其行为);可以对其进行序列化和反序列化。工厂的职责可能是反序列化保存的任务,重新创建状态并返回完整的任务对象。然后,PerformTask
方法可以简单地检查必须运行哪个步骤,类似于我前面的评论。
class SomeTask2
{
...
public SomeTask2(SomeClass someImportantReference){...}
public override IEnumerator PerformTask
{
IThinkYouKnowWhereThisIsGoing();
LemmeJustUseSomeObject(someImportantReference);
yield break;
}
}