OOP事件日志器开发:如何将I_Logger接口地址传递至嵌套FB?
TwinCAT OOP自定义日志器层级传递解决方案
一、统一基类抽象,解决层级传递核心问题
先定义一个所有层级元素(设备、组件、总成、工位)都继承的基类FB_BaseElement,内置日志器接口引用和传递逻辑,确保所有嵌套FB都能统一获取日志器:
INTERFACE I_Logger METHOD LogEvent VAR_INPUT sMessage : STRING; eLevel : LOG_LEVEL; // 自行定义枚举:Info/Warning/Error等 END_VAR END_METHOD END_INTERFACE FUNCTION_BLOCK FB_BaseElement VAR _logger : I_Logger; // 日志器接口引用 END_VAR END_FUNCTION_BLOCK // 对外暴露的日志器注入方法 METHOD PUBLIC SetLogger VAR_INPUT logger : I_Logger; END_VAR _logger := logger; // 触发子元素的日志器传递 THIS.SetChildLoggers(logger); END_METHOD // 子类需重写的子元素处理方法 METHOD PROTECTED SetChildLoggers VAR_INPUT logger : I_Logger; END_VAR // 空实现,子类根据自身包含的子元素重写 END_METHOD
二、各层级元素的具体实现
1. 最底层设备类
设备无下级元素,只需重写空的SetChildLoggers,并在业务逻辑中调用日志器:
FUNCTION_BLOCK FB_Device EXTENDS FB_BaseElement METHOD PROTECTED OVERRIDE SetChildLoggers // 设备无嵌套元素,空实现 END_METHOD METHOD PUBLIC RunOperation // 业务逻辑示例 IF _logger <> NULL THEN _logger.LogEvent('设备启动运行', LOG_LEVEL.Info); END_IF; END_METHOD END_FUNCTION_BLOCK
2. 组件类(包含多个设备)
重写SetChildLoggers遍历所有子设备,传递日志器:
FUNCTION_BLOCK FB_Component EXTENDS FB_BaseElement VAR _devices : ARRAY[1..8] OF FB_Device; // 根据实际需求定义数量 END_VAR METHOD PROTECTED OVERRIDE SetChildLoggers VAR_INPUT logger : I_Logger; END_VAR FOR i := 1 TO 8 DO _devices[i].SetLogger(logger); END_FOR; END_METHOD END_FUNCTION_BLOCK
3. 工位/区域类(包含组件/设备)
同理,遍历自身所有子元素传递日志器:
FUNCTION_BLOCK FB_Workstation EXTENDS FB_BaseElement VAR _components : ARRAY[1..4] OF FB_Component; _singleDevices : ARRAY[1..2] OF FB_Device; END_VAR METHOD PROTECTED OVERRIDE SetChildLoggers VAR_INPUT logger : I_Logger; END_VAR // 传递给组件 FOR i := 1 TO 4 DO _components[i].SetLogger(logger); END_FOR; // 传递给独立设备 FOR i := 1 TO 2 DO _singleDevices[i].SetLogger(logger); END_FOR; END_METHOD END_FUNCTION_BLOCK
三、外层注入与自动传递
在主程序或外层FB中,只需给最顶层的工位/区域注入日志器,所有嵌套的内层FB会自动获取到:
VAR g_CustomLogger : FB_CustomLogger; // 实现I_Logger接口的自定义日志器 g_MainWorkstation : FB_Workstation; END_VAR // 初始化阶段执行一次 g_MainWorkstation.SetLogger(g_CustomLogger);
四、关于装饰器模式的适配说明
TwinCAT的OOP对装饰器模式支持有限(比如缺乏动态代理、接口实例化限制),所以不建议强行用装饰器实现日志器传递。上面的基类继承+递归传递方案更贴合TwinCAT的运行机制,而且维护成本更低——新增层级元素时,只需继承FB_BaseElement并重写SetChildLoggers即可。
内容的提问来源于stack exchange,提问作者TL140
相关产品推荐
相关产品推荐

