Files
Future/Future.Contract/Instruction/SpaceInstructBase.cs

274 lines
12 KiB
C#
Raw Normal View History

2025-08-30 17:19:57 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Future.Contract
{
/// <summary>
/// 指令空间:有独立的参数和信道上下文
/// </summary>
public abstract class SpaceInstructBase : StructInstructBase
{
#region
/// <summary>
/// 指令空间的序列标签Label种子
/// </summary>
public int LabelSeed { get; set; }
protected override void DoVerify(IOutputChannel infoChannel)
{
this.ReferenceMapping.Clear();
this.BuildReferenceMapping(this.ReferenceMapping);
this.InsturctContext.Clear();
this.ParameterContext.Clear();
this.ChannelContext.Clear();
}
protected override string CheckParent(FutureInstruct parentInst)
{
if (parentInst != null)
return "指令空间不可以成为任何一个指令的子级指令!";
else return null;
}
#endregion
#region
/// <summary>
/// 指令序列的执行状态
/// </summary>
public ESpaceState State { get; set; }
/// <summary>
/// 启动指令序列的执行逻辑,自类可以重写这个逻辑
/// </summary>
/// <param name="infoOutChannel">用于输出验证信息或其它过程提示信息的输出通道</param>
/// <param name="expansionChannels">消息输出管道、态势感知管道、报告生成管道等</param>
/// <param name="needThread">是否需要开启独立线程还执行?默认=false</param>
/// <returns>如果失败则返回原因正常启动返回“null”</returns>
public virtual string Start(IOutputChannel infoOutChannel, IEnumerable<IOutputChannel> expansionChannels = null, bool needThread = false)
{
if (this.State != ESpaceState.Finished) return $"当前指令序列正在执行或暂停,不可重复启动!";
//先执行一次指令校验
this.Verify(infoOutChannel);
if (infoOutChannel.OutputMessageCount > 0) return $"当前指令序列运行校验失败,存在【{infoOutChannel.OutputMessageCount}】个问题,请检查指令序列的配置!";
//清空所有上下文
this.__ExpansionChannels.Clear();
this.ReferenceMapping.Clear();
this.InsturctContext.Clear();
this.ParameterContext.Clear();
this.ChannelContext.Clear();
this.__ExpansionChannels.AddRange(expansionChannels);
//个性化启动准备
string startMsg = this.OnPreStart();
if (startMsg != null) return startMsg;
this.State = ESpaceState.Normal;
if (needThread)
{
//TODO:指令执行逻辑=>启动线程并使用新线程执行Execute方法或DoExecute方法
}
else this.Execute();
return null;
}
/// <summary>
/// 子类必须实现的启动准备逻辑
/// </summary>
/// <returns>如果启动准备失败则需要返回失败原因</returns>
protected abstract string OnPreStart();
/// <summary>
/// 发送暂停通知,等待执行引擎在执行到检查周期时开始等待
/// </summary>
/// <returns>如果失败则返回原因</returns>
public virtual string Pause() { return null; }
/// <summary>
/// 发送继续通知,等待执行引擎在执行到检查周期时继续执行
/// </summary>
/// <returns>如果失败则返回原因</returns>
public virtual string Rouse() { return null; }
/// <summary>
/// 发出终止通知,等待执行引擎在执行到检查周期时自动停止
/// </summary>
/// <returns>如果失败则返回原因</returns>
public virtual string Break() { return null; }
/// <summary>
/// 强制终止,强制终止引擎的执行线程,可能会造成未知错误
/// </summary>
/// <returns>如果失败则返回原因</returns>
public virtual string Abort() { return null; }
/// <summary>
/// 执行结束时需要进行的操作
/// </summary>
public abstract void OnFinished();
/// <summary>
/// 当执行完成时发出的通知
/// </summary>
public event EventHandler Finished;
#endregion
#region
private readonly List<IOutputChannel> __ExpansionChannels = new List<IOutputChannel>();
/// <summary>
/// 扩展信道表,用于进行态势感知、报告生成等行为的扩展信道表
/// </summary>
/// <returns></returns>
public IEnumerable<IOutputChannel> OutChannels() { yield break; }
#endregion
#region
/// <summary>
/// 存储一个指令空间中所有指令的“值”
/// </summary>
private readonly Dictionary<string, string> InsturctContext = new Dictionary<string, string>();
/// <summary>
/// 以指令为单位存储一个指令空间中所有指令的参数值
/// </summary>
private readonly Dictionary<string, Dictionary<string, string>> ParameterContext = new Dictionary<string, Dictionary<string, string>>();
/// <summary>
/// 设置一个参数的值,如果这个参数尚未存在于上下文中则创建上下文参数
/// </summary>
/// <param name="key">上下文参数名</param>
/// <param name="value">参数值</param>
public void SetParameter(string key, string value)
{
string[] args = key.Split(new char[] { FutureInstruct.PR_SplitChar, FutureInstruct.PR_StartChar }, StringSplitOptions.RemoveEmptyEntries);
switch (args.Length)
{
case (1):
{
if (this.InsturctContext.ContainsKey(args[0]))
InsturctContext[args[0]] = value;
else InsturctContext.Add(args[0], value);
}
break;
case (2):
{
if (!this.ParameterContext.ContainsKey(args[0]))
this.ParameterContext.Add(args[0], new Dictionary<string, string>());
Dictionary<string, string> param = this.ParameterContext[args[0]];
if (param.ContainsKey(args[1])) param[args[1]] = value;
else param.Add(args[1], value);
}
break;
default: return;
}
}
/// <summary>
/// 获取一个上下文参数的值,如果这个上下文参数不存在则返回默认值
/// </summary>
/// <param name="key">上下文参数名</param>
/// <param name="default">默认值</param>
/// <returns>参数的值</returns>
public string GetParameter(string key, string @default)
{
string[] args = key.Split(new char[] { FutureInstruct.PR_SplitChar, FutureInstruct.PR_StartChar }, StringSplitOptions.RemoveEmptyEntries);
switch (args.Length)
{
case (1):
{
if (this.InsturctContext.ContainsKey(args[0]))
return this.InsturctContext[args[0]];
else return @default;
}
case (2):
{
if (!this.ParameterContext.ContainsKey(args[0]))
this.ParameterContext.Add(args[0], new Dictionary<string, string>());
Dictionary<string, string> param = this.ParameterContext[args[0]];
if (param.ContainsKey(args[1])) return param[args[1]];
else return @default;
}
default: return @default;
}
}
/// <summary>
/// 检查上下文中是否存在制定名称的参数
/// </summary>
/// <param name="key">上下文参数名称</param>
/// <returns>是/否</returns>
public bool IsExistParameter(string key)
{
string[] args = key.Split(new char[] { FutureInstruct.PR_SplitChar, FutureInstruct.PR_StartChar }, StringSplitOptions.RemoveEmptyEntries);
switch (args.Length)
{
case (1):
{
if (this.InsturctContext.ContainsKey(args[0])) return true;
}
break;
case (2):
{
if (!this.ParameterContext.ContainsKey((string)args[0])) return false;
if (this.ParameterContext[args[0]].ContainsKey(args[1])) return true;
break;
}
default: return false;
}
return false;
}
#endregion
#region
/// <summary>
/// 以信道名称为Key存储当前指令空间中所有已经完成初始化化的通信信道
/// </summary>
private readonly Dictionary<string, CommChannel> ChannelContext = new Dictionary<string, CommChannel>();
/// <summary>
/// 向上下文注册信道,如果信道名称已经存在则会报错
/// </summary>
/// <param name="key">通信信道名称</param>
/// <param name="channel">信道实例</param>
public void SetChannel(string key, CommChannel channel)
{
key = key.TrimStart(FutureInstruct.PR_StartChar);
if (!this.ChannelContext.ContainsKey(key))
this.ChannelContext.Add(key, channel);
else this.ChannelContext[key] = channel;
}
/// <summary>
/// 从上下文中获取通信信道实例
/// </summary>
/// <param name="key">通信信道名称</param>
/// <returns>获得的通信信道实例</returns>
public CommChannel GetChannel(string key)
{
key = key.TrimStart(FutureInstruct.PR_StartChar);
if (!ChannelContext.ContainsKey(key)) return this.ChannelContext[key];
return null;
}
/// <summary>
/// 检查上下文中是否存在制定名称的通信信道
/// </summary>
/// <param name="key">通信信道名称</param>
/// <returns>是/否</returns>
public bool IsExistChannel(string key)
{
key = key.TrimStart(FutureInstruct.PR_StartChar);
return this.ChannelContext.ContainsKey(key);
}
#endregion
#region
/// <summary>
/// 指令引用表:指示那些指令被其它指令引用,用于加速指令的运行,减小指令上下文与参数上下文的内存占用
/// </summary>
private readonly List<string> ReferenceMapping = new List<string>();
/// <summary>
/// 检查一个指令或是指令的参数是否被其它指令引用;只允许在执行态被使用
/// </summary>
/// <param name="identify">指令或是参数的标识符</param>
/// <returns>如果被引用则返回True,否则返回False</returns>
public bool IsExistReference(string identify)
{
if (string.IsNullOrEmpty(identify)) return false;
return this.ReferenceMapping.Contains(identify);
}
#endregion
}
}