c++ - 如何在每个新模块中自动注入(inject)辅助类?

标签 c++ architecture macros module code-generation

开发一个模块化的应用程序,我想在每个模块中注入(inject)一些帮助类。这应该自动发生。请注意,我的助手有状态,所以我不能只将它们设为静态并在需要的地方包含它们。

我可以将所有助手存储在一个带有字符串键的映射中,并使其可供所有模块继承自的抽象基类使用。

std::unordered_map<std::string, void*> helpers;
RendererModule renderer = new RendererModule(helpers); // argument is passed to
                                                       // base class constructor

然后在模块内部,我可以像这样访问助手。

std::string file = (FileHelper*)helpers["file"]->Read("C:/file.txt");

但相反,我想像这样访问助手。

std::string file = File->Read("C:/file.txt");

为此,目前我分别为模块基类中的所有助手定义成员,并为每个特定模块设置它们。

FileHelper file = new FileHelper(); // some helper instances are passed to
                                    // multiple modules, while others are
                                    // newly created for each one
RendererModule renderer = new RendererModule();
renderer->File = file;

有没有办法自动执行此操作,以便在向应用程序添加新帮助器时不必更改模块代码,同时保留第二种语法?我不太熟悉 C 宏,所以我不知道它们是否能够做到这一点。

最佳答案

认为我明白你的困境是什么,但我没有好的解决方案。但是,由于没有其他答案,我将贡献我的两分钱。

我结合使用了一些策略来帮助我解决这些问题:

  1. 如果助手实例确实是特定于模块的,我会让模块本身在内部创建和管理它。
  2. 如果我不想让模块知道助手的创建或销毁,或者如果助手实例的生命周期与使用它的模块无关,或者如果我想共享几个模块中的一个助手实例,我在外部创建它并将引用传递给模块的入口点构造函数。将其传递给构造函数的好处是可以显式依赖。
  3. 如果助手的数量很多(比如超过 2-3 个),我会创建一个包含所有内容的 struct(或简单的 class)指针并将该结构传递给模块或子系统的构造函数。例如:

    struct Platform { // I sometimes call it "Environment", etc.
        FileHelper * file;
        LogHelper * log;
        MemoryHelper * mem;
        StatsHelper * stats;
    };
    

    注意:这不是一个特别好的或安全的解决方案,但它并不比管理不同的指针差,而且很简单。

以上都是假设helpers不依赖于模块(即它们处于较低的依赖级别抽象并且对模块一无所知。)如果一些helpers更接近于模块,也就是说,如果你开始想要注入(inject)模块对模块的相互依赖,上述策略真的崩溃了。

在这些情况下(显然经常发生),我发现集中式 ModuleManager 单例(可能是全局对象)是最好的。您显式地将您的模块注册到其中,以及 显式 初始化顺序,它会构建所有模块。模块可以通过名称向此 ModuleManager 请求对其他模块的引用(有点像字符串到模块指针的映射),但它们只执行一次并以它们想要的任何方式在内部存储指针,以便方便和快速访问。

但是,为了防止困惑的生命周期和销毁顺序问题,任何时候构建或销毁模块时,ModuleManager 都会通过回调通知所有其他模块,因此它们有机会更新其内部指针以避免悬空指针和其他问题。

就是这样。顺便说一下,您可能想要研究与“服务定位器”模式相关的文章和实现。

关于c++ - 如何在每个新模块中自动注入(inject)辅助类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18289576/

相关文章:

java - 模块化 - 设计模式 - 架构

docker - 我应该为我的 Web 应用程序使用单独的 Docker 容器吗?

c - #define x 2|0 在 C 中

c++ - 线程或类错误 c++11

c++ - 函数不应在 block 范围内声明

C++ 自定义列表删除节点

cocoa - 是否存在另一种可用的 "Application architecture"?

c++ - Apple Mach O 链接器

c++ - 带有引号和反斜杠的 C/C++ 宏错误

c - 如何通过宏在两个空指针之间复制内存?