Files
Future/Future.Contract/Instruction/SpaceInstructBase.cs
2025-08-30 17:19:57 +08:00

274 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}