You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:52:40