具有可变模板成员功能的类的依赖注入

问题描述 投票:0回答:1

上下文:我有一个第三方记录器类,该类具有采用任意nr参数的可变参数函数。在我的代码库中,我有几个需要记录信息的类。我希望能够通过依赖关系注入来提供实例,而不是对第三方记录器类进行硬编码。这样,如果我想在运行时禁用日志记录,我还可以提供一个空对象。

示例代码:

//third partycode
class Logger{
public:
    template<typename ...Ts>
    void Log(const char * format, Ts... params);
};

//own code
class NullLogger{
public:
    template<typename ...Ts>
    void Log(const char * format, Ts... params); // doesn't do actual logging
};

class SomeClass{
public:
    template<typename LOGGER>
    void SetLogger(std::shared_ptr<LOGGER> logger){ m_logger = logger;}

    void SomeFunction(){
        m_logger->Log("test {0},{1}", 42, 13.37);
    }
private:
    ??? m_logger;
};

问题:如何使以上代码起作用?

我的要求:

  1. 我不想使SomeClass成为模板类。
  2. 我无法更改第三方记录器(我可以为自己的NullLogger选择其他设计)
  3. 我希望能够交换SomeClass正在使用的记录器在运行时。
c++ dependency-injection variadic-templates
1个回答
0
投票

您将无法注入任何非可注入的依赖项。也许是logger,您将尝试查看如何实现Log功能。Log函数是模板,因此现在不能被覆盖:

//third partycode
class Logger{
public:
    template<typename ...Ts>
    void Log(const char * format, Ts... params);
};

您应该检查功能日志的实现方式

    template<typename ...Ts>
    void Log(const char * format, Ts... params)
    {maybe it calls here any virtual_function(format, params...);}

如果它调用任何虚函数,您可以覆盖它:

//own code
class NullLogger: Logger{
public:
    virtual_function(const char * format, Ts... params); // override
};

也许还有另一种方式,例如,您可以提供Logger使用的任何特定流对象。因此,如果您成功完成以上所有步骤,便可以注射,否则就别无选择:

class SomeClass{
public:
    void SetLogger(std::shared_ptr<Logger> logger){ m_logger = logger;}

    void SomeFunction(){
        m_logger->Log("test {0},{1}", 42, 13.37);
    }
private:
    std::shared_ptr<Logger> m_logger;
};
© www.soinside.com 2019 - 2024. All rights reserved.