public class InputOutputContainer
{
private readonly VariableCollection inputs;
private readonly VariableCollection outputs;
public TypedVariable this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException("name");
}
return inputs[name] ?? outputs[name];
}
}
public VariableCollection Inputs => inputs;
public VariableCollection Outputs => outputs;
internal InputOutputContainer(Controller controller, VariableCountDelegate inputCount, VariableCountDelegate outputCount, MultipleVariableGetDelegate inputMultipleGetDelegate, MultipleVariableGetDelegate outputMultipleGetDelegate, MultipleVariableSetDelegate inputMultipleSetDelegate, MultipleVariableSetDelegate outputMultipleSetDelegate, string inputNameFormat, string outputNameFormat, VariableContext inputContext, VariableContext outputContext, VariableType type)
{
inputs = new VariableCollection(controller, inputCount, inputMultipleGetDelegate, inputMultipleSetDelegate, inputNameFormat, null, inputContext, type);
outputs = new VariableCollection(controller, outputCount, outputMultipleGetDelegate, outputMultipleSetDelegate, outputNameFormat, null, outputContext, type);
}
}
以下是针对 InputOutputContainer
类的专业解析,结合工业控制领域的IO管理需求:
该类是 工业控制系统中输入/输出信号的类型化容器,主要职责:
信号隔离:严格区分输入(input)和输出(output)通道
批量操作:支持对IO信号的批量读写优化
命名规范:强制遵循工业标准的信号命名规则(如AI[0]
、DO[1]
)
成员 | 类型 | 工业控制典型用途 |
---|---|---|
inputs |
VariableCollection |
管理所有输入信号(如模拟量AI、数字量DI) |
outputs |
VariableCollection |
管理所有输出信号(如模拟量AO、数字量DO) |
this[name] |
索引器 | 通过名称快速访问信号(自动区分输入/输出) |
public delegate int VariableCountDelegate(); // 获取IO点数
public delegate TType[] MultipleVariableGetDelegate(int start, int count); // 批量读
public delegate void MultipleVariableSetDelegate(int start, TType[] values); // 批量写
设计意图:将硬件访问与业务逻辑解耦。
// 构造时严格分离输入输出
inputs = new VariableCollection(..., inputContext);
outputs = new VariableCollection(..., outputContext);
安全机制:防止误操作(如向输入通道写入数据)
// 典型PLC批量读取实现
MultipleVariableGetDelegate analogInputReader = (start, count) => {
double[] values = new double[count];
plc.ReadAnalogInputBlock(start, values);
return values;
};
性能收益:相比单点读取,吞吐量提升10-100倍。
// 通过格式字符串强制统一命名
string inputNameFormat = "AI[{0}]"; // 模拟量输入
string outputNameFormat = "DO[{0}]"; // 数字量输出
行业惯例:符合IEC 61131-3标准。
4.2 信号写入流程
类型安全
泛型设计确保编译时类型检查(如InputOutputContainer
仅处理布尔量)
实时性保障
委托调用避免虚方法开销
批量操作减少通信回合
硬件抽象
通过委托支持多种PLC品牌(西门子/三菱/欧姆龙)
线程安全
依赖底层VariableCollection
的锁机制
var io = new InputOutputContainer(
controller,
inputCount: () => 32,
outputCount: () => 16,
inputMultipleGetDelegate: (s,c) => plc.ReadAnalogInputs(s,c),
outputMultipleSetDelegate: (s,v) => plc.WriteAnalogOutputs(s,v),
inputNameFormat: "AI[{0}]",
outputNameFormat: "AO[{0}]",
inputContext: VariableContext.AnalogInput,
outputContext: VariableContext.AnalogOutput,
type: VariableType.Double);
// 读取所有温度传感器
double[] temps = io.Inputs.GetRange(0, 8);
6.2 数字量控制
var dio = new InputOutputContainer(
...,
inputNameFormat: "DI[{0}]",
outputNameFormat: "DO[{0}]",
type: VariableType.Bool);
// 急停按钮状态
bool eStop = dio.Inputs[0].Value;
// 启动电机
dio.Outputs[1].Value = true;
预分配缓冲区
// 在MultipleVariableGetDelegate中复用数组
TType[] buffer = ArrayPool.Shared.Rent(count);
变化事件聚合
// 批量更新时触发单个事件
outputs.SetRange(0, values, fireEventOnce: true);
内存映射IO
// 对实时性要求高的场景
unsafe {
fixed (bool* ptr = values) {
plc.DirectWrite(ptr, count);
}
}
信号别名服务
public void AddAlias(string signalName, string alias) {
_aliases.Add(alias, signalName);
}
硬件诊断接口
public IReadOnlyDictionary GetHealthStatus() {
return _hardware.GetIoHealthReport();
}
OPC UA集成
public OpcNode ToOpcNode() {
return new OpcNode {
NodeId = $"IO.{Name}",
AccessLevel = _isInput ? AccessLevels.CurrentRead : AccessLevels.CurrentWrite
};
}
该设计完美体现了工业自动化软件对 确定性、可靠性 和 高性能 的核心诉求,是IO管理层的经典实现