重写了Script的解释器代码,使其更加直观。重写了流程控制的部分代码,分离运行环境IOC与流程IOC。

This commit is contained in:
fengjiayi
2025-07-18 22:45:06 +08:00
parent 88de5a21f5
commit fc05cd662b
38 changed files with 567 additions and 1418 deletions

View File

@@ -1,70 +0,0 @@
using Net462DllTest.Signal;
using Net462DllTest.Trigger;
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Net462DllTest.LogicControl
{
[AutoRegister]
[DynamicFlow("[View]")]
public class ViewLogicControl
{
private readonly ViewManagement ViewManagement;
public ViewLogicControl(ViewManagement ViewManagement)
{
this.ViewManagement = ViewManagement;
}
#region
[NodeAction(NodeType.Flipflop, "等待视图命令")]
public async Task<IFlipflopContext<int>> WaitTask(CommandSignal command)
{
var result = await ViewManagement.WaitTriggerWithTimeoutAsync<int>(command, TimeSpan.FromHours(10));
if (result.Type == TriggerDescription.Overtime)
{
return new FlipflopContext<int>(FlipflopStateType.Cancel, result.Value);
}
else
{
return new FlipflopContext<int>(FlipflopStateType.Succeed, result.Value);
}
}
#endregion
[NodeAction(NodeType.Action, "打开窗体(转换器)")]
public void OpenForm2([EnumTypeConvertor(typeof(FromValue))] Form form, bool isTop = true)
{
// 枚举转换为对应的Type并自动实例化
ViewManagement.OpenView(form, isTop);
}
[NodeAction(NodeType.Action, "关闭指定类型的所有窗体")]
public void CloseForm(IDynamicContext context, FromValue fromId = FromValue.FromWorkBenchView)
{
var fromType = EnumHelper.GetBoundValue<FromValue, Type>(fromId, attr => attr.Value);
if (fromType is null) return;
ViewManagement.CloseView(fromType);
}
}
}

View File

@@ -72,26 +72,12 @@
<Compile Include="Enums\PlcVarName.cs" />
<Compile Include="LogicControl\PlcLogicControl.cs" />
<Compile Include="LogicControl\ParkingLogicControl.cs" />
<Compile Include="LogicControl\ViewLogicControl.cs" />
<Compile Include="Enums\FromValue.cs" />
<Compile Include="Signal\CommandSignal.cs" />
<Compile Include="Signal\PLCVarSignal.cs" />
<Compile Include="Trigger\ViewManagement.cs" />
<Compile Include="Utils\GSModel.cs" />
<Compile Include="Utils\RelayCommand.cs" />
<Compile Include="ViewModel\FromWorkBenchViewModel.cs" />
<Compile Include="View\FromWorkBenchView.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\FromWorkBenchView.Designer.cs">
<DependentUpon>FromWorkBenchView.cs</DependentUpon>
</Compile>
<Compile Include="View\TestFormView.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\TestFormView.Designer.cs">
<DependentUpon>TestFormView.cs</DependentUpon>
</Compile>
<Compile Include="Web\FlowController.cs" />
<Compile Include="Web\PlcSocketService.cs" />
</ItemGroup>
@@ -101,14 +87,6 @@
<Name>Serein.Library</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="View\FromWorkBenchView.resx">
<DependentUpon>FromWorkBenchView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\TestFormView.resx">
<DependentUpon>TestFormView.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>

View File

@@ -1,110 +0,0 @@
namespace Net462DllTest
{
partial class FromWorkBenchView
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.textBoxPlcInfo = new System.Windows.Forms.TextBox();
this.button2 = new System.Windows.Forms.Button();
this.listBoxCommand = new System.Windows.Forms.ListBox();
this.textBoxSpaceNum = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(220, 56);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(65, 23);
this.button1.TabIndex = 0;
this.button1.Text = "查看状态";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBoxPlcInfo
//
this.textBoxPlcInfo.Location = new System.Drawing.Point(35, 24);
this.textBoxPlcInfo.Name = "textBoxPlcInfo";
this.textBoxPlcInfo.ReadOnly = true;
this.textBoxPlcInfo.Size = new System.Drawing.Size(250, 21);
this.textBoxPlcInfo.TabIndex = 1;
//
// button2
//
this.button2.Location = new System.Drawing.Point(205, 181);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(80, 23);
this.button2.TabIndex = 2;
this.button2.Text = "触发";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// listBoxCommand
//
this.listBoxCommand.FormattingEnabled = true;
this.listBoxCommand.ItemHeight = 12;
this.listBoxCommand.Location = new System.Drawing.Point(35, 85);
this.listBoxCommand.Name = "listBoxCommand";
this.listBoxCommand.Size = new System.Drawing.Size(250, 88);
this.listBoxCommand.TabIndex = 6;
//
// textBoxSpaceNum
//
this.textBoxSpaceNum.Location = new System.Drawing.Point(35, 183);
this.textBoxSpaceNum.Name = "textBoxSpaceNum";
this.textBoxSpaceNum.Size = new System.Drawing.Size(106, 21);
this.textBoxSpaceNum.TabIndex = 7;
this.textBoxSpaceNum.Text = "104";
//
// FromWorkBenchView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(341, 251);
this.Controls.Add(this.textBoxSpaceNum);
this.Controls.Add(this.listBoxCommand);
this.Controls.Add(this.button2);
this.Controls.Add(this.textBoxPlcInfo);
this.Controls.Add(this.button1);
this.Name = "FromWorkBenchView";
this.Text = "Form1";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FromWorkBenchView_FormClosing);
this.Load += new System.EventHandler(this.FromWorkBenchView_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBoxPlcInfo;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.ListBox listBoxCommand;
private System.Windows.Forms.TextBox textBoxSpaceNum;
}
}

View File

@@ -1,59 +0,0 @@
using Net462DllTest.Signal;
using Net462DllTest.ViewModel;
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Windows.Forms;
namespace Net462DllTest
{
public partial class FromWorkBenchView : Form
{
private FromWorkBenchViewModel ViewModel;
public FromWorkBenchView(IFlowEnvironment env)
{
InitializeComponent();
ViewModel = env.IOC.Get<FromWorkBenchViewModel>();
if (ViewModel is null)
{
SereinEnv.WriteLine(InfoType.INFO, "创建对象并注入依赖项");
ViewModel = env.IOC.CreateObject<FromWorkBenchViewModel>();
}
BindData();
}
private void BindData()
{
textBoxPlcInfo.DataBindings.Add(nameof(textBoxPlcInfo.Text), ViewModel, nameof(ViewModel.DeviceInfo), false, DataSourceUpdateMode.OnPropertyChanged);
textBoxSpaceNum.DataBindings.Add(nameof(textBoxSpaceNum.Text), ViewModel, nameof(ViewModel.SpcaeNumber), false, DataSourceUpdateMode.OnPropertyChanged);
listBoxCommand.DataSource = Enum.GetValues(typeof(CommandSignal));
listBoxCommand.DataBindings.Add(nameof(listBoxCommand.SelectedItem), ViewModel, nameof(ViewModel.SelectedSignal), false, DataSourceUpdateMode.OnPropertyChanged);
listBoxCommand.SelectedIndexChanged += (s, e) => listBoxCommand.DataBindings[nameof(listBoxCommand.SelectedItem)].WriteValue();
}
private void FromWorkBenchView_Load(object sender, EventArgs e)
{
}
private void FromWorkBenchView_FormClosing(object sender, FormClosingEventArgs e)
{
ViewModel.CommandCloseForm.Execute();
}
private void button2_Click(object sender, EventArgs e)
{
ViewModel.CommandGetParkingSpace.Execute();
}
private void button1_Click(object sender, EventArgs e)
{
ViewModel.CommandViewPlcInfo.Execute();
}
}
}

View File

@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -1,62 +0,0 @@
using System;
namespace Net462DllTest.View
{
partial class TestFormView
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(167, 58);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "测试";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// TestFormView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(254, 118);
this.Controls.Add(this.button1);
this.Name = "TestFormView";
this.Text = "TeseForm";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
}
}

View File

@@ -1,19 +0,0 @@
using System;
using System.Windows.Forms;
namespace Net462DllTest.View
{
public partial class TestFormView : Form
{
public TestFormView()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}

View File

@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -1,140 +0,0 @@
using Net462DllTest.Model;
using Net462DllTest.Signal;
using Net462DllTest.Trigger;
using Net462DllTest.Utils;
using Serein.Library.Network.WebSocketCommunication;
using System.ComponentModel;
namespace Net462DllTest.ViewModel
{
public class LibSpace
{
public string SpaceNum { get; set; }
public string PlateNumber { get; set; }
public override string ToString()
{
return $"{nameof(SpaceNum)}{SpaceNum}{nameof(PlateNumber)}{PlateNumber}";
}
}
public class FromWorkBenchViewModel : INotifyPropertyChanged
{
private readonly SiemensPlcDevice Device;
private readonly ViewManagement viewManagement;
private readonly PlcVarModelDataProxy plcVarModelDataProxy;
public FromWorkBenchViewModel(SiemensPlcDevice Device,
ViewManagement viewManagement,
PlcVarModelDataProxy plcVarModelDataProxy,
WebSocketServer webSocketServer)
{
this.Device = Device;
this.viewManagement = viewManagement;
this.plcVarModelDataProxy = plcVarModelDataProxy;
InitCommand(); // 初始化指令
}
#region
private string _spcaeNumber;
public string SpcaeNumber
{
get { return _spcaeNumber; }
set
{
if (_spcaeNumber != value)
{
_spcaeNumber = value;
OnPropertyChanged(nameof(SpcaeNumber));
}
}
}
private CommandSignal _selectedSignal;
public CommandSignal SelectedSignal
{
get { return _selectedSignal; }
set
{
if (_selectedSignal != value)
{
_selectedSignal = value;
OnPropertyChanged(nameof(SelectedSignal));
}
}
}
private string _deviceInfo;
public string DeviceInfo
{
get { return _deviceInfo; }
set
{
if (_deviceInfo != value)
{
_deviceInfo = value;
OnPropertyChanged(nameof(DeviceInfo));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region
/// <summary>
/// 查看PLC信息
/// </summary>
public RelayCommand CommandViewPlcInfo { get; private set; }
/// <summary>
/// 调取车位
/// </summary>
public RelayCommand CommandGetParkingSpace { get; private set; }
/// <summary>
/// 关闭窗体
/// </summary>
public RelayCommand CommandCloseForm { get; private set; }
public void InitCommand()
{
CommandViewPlcInfo = new RelayCommand((p) =>
{
DeviceInfo = Device?.ToString();
});
CommandGetParkingSpace = new RelayCommand((p) =>
{
_ = viewManagement.InvokeTriggerAsync(SelectedSignal, SpcaeNumber);
});
CommandCloseForm = new RelayCommand((p) =>
{
});
}
#endregion
}
}

View File

@@ -33,23 +33,25 @@ namespace Net462DllTest.Web
[NodeAction(NodeType.Init)]
public void Init(IDynamicContext context)
{
context.Env.IOC.Register<WebSocketServer>();
context.Env.IOC.Register<WebSocketClient>();
var ioc = context.Env.FlowControl.IOC;
ioc.Register<WebSocketServer>();
ioc.Register<WebSocketClient>();
context.Env.IOC.Register<IRouter, Router>();
context.Env.IOC.Register<WebApiServer>();
ioc.Register<IRouter, Router>();
ioc.Register<WebApiServer>();
}
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
public void Loading(IDynamicContext context)
{
var ioc = context.Env.FlowControl.IOC;
// 注册控制器
context.Env.IOC.Run<IRouter, WebApiServer>((router, apiServer) => {
ioc.Run<IRouter, WebApiServer>((router, apiServer) => {
router.AddHandle(typeof(FlowController));
apiServer.Start("http://*:8089/"); // 开启 Web Api 服务
});
context.Env.IOC.Run<WebSocketServer>(async (socketServer) => {
ioc.Run<WebSocketServer>(async (socketServer) => {
socketServer.MsgHandleHelper.AddModule(this, (ex, recover) =>
{
recover(new
@@ -61,7 +63,7 @@ namespace Net462DllTest.Web
});
await socketServer.StartAsync("http://localhost:5005/"); // 开启 Web Socket 监听
});
context.Env.IOC.Run<WebSocketClient>(async client => {
ioc.Run<WebSocketClient>(async client => {
await client.ConnectAsync("ws://localhost:5005/"); // 连接到服务器
});
}
@@ -69,12 +71,13 @@ namespace Net462DllTest.Web
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
public void Exit(IDynamicContext context)
{
context.Env.IOC.Run<WebApiServer>((apiServer) =>
var ioc = context.Env.FlowControl.IOC;
ioc.Run<WebApiServer>((apiServer) =>
{
apiServer?.Stop(); // 关闭 Web 服务
});
context.Env.IOC.Run<WebSocketServer>((socketServer) =>
ioc.Run<WebSocketServer>((socketServer) =>
{
socketServer.MsgHandleHelper.RemoveModule(this);
socketServer?.Stop(); // 关闭 Web 服务