简体   繁体   English

使用可变参数模板成员 function 的 class 的依赖注入

[英]Dependency injection of class with variadic template member function

Context: I have a third party logger class that has a variadic log function taking an arbitrary nr of parameters.上下文:我有一个第三方记录器 class 有一个可变参数日志 function 采用任意 nr 参数。 In my code base I have several classes that need to log information.在我的代码库中,我有几个需要记录信息的类。 Instead of hardcoding this 3rd party logger class I want to be able to supply an instance through dependency injection.我不想硬编码这个第 3 方记录器 class 我希望能够通过依赖注入提供一个实例。 This way I can also supply for example a null object if I want to disable logging at run time.这样,如果我想在运行时禁用日志记录,我还可以提供例如 null object。

Example code:示例代码:

//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;
};

Question: How can I make above code work?问题:我怎样才能使上面的代码工作?

My requirements:我的要求:

  1. I do not want to make SomeClass a template class.我不想让 SomeClass 成为模板 class。
  2. I can not change the third party Logger(I can choose a different design for my own NullLogger)我无法更改第三方 Logger(我可以为我自己的 NullLogger 选择不同的设计)
  3. I want to be able to swap out the logger that is being used by SomeClass at run time.我希望能够在运行时更换 SomeClass 正在使用的记录器。

You will not be able to inject any dependence that is not designed to be injectable.您将无法注入任何并非设计为可注入的依赖项。 Maybe logger is, you will try to see how Log function is implemented.也许 logger 是,你会尝试看看 Log function 是如何实现的。 The Log function is template, so it can't be overridden now:日志 function 是模板,所以现在不能被覆盖:

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

What you should to is to check how the function Log is implemented您应该检查 function 日志是如何实现的

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

If it calls any virtual function you can override it:如果它调用任何虚拟 function 你可以覆盖它:

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

Maybe there is another way, for instance you could provide any specific stream objects to be used by Logger.也许还有另一种方式,例如您可以提供任何特定的 stream 对象以供 Logger 使用。
So if you succeed with above you have everything injectable, otherwise there is no choice:因此,如果您成功完成上述操作,您将拥有所有可注射的东西,否则别无选择:

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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM