我使用的注入器模块体现了DI框架的大部分Guice API。
我试图完成的是Guice对@Named绑定注释所做的工作。也就是说,使用injector.Module
覆盖configure
方法,并使用Binder绑定多个相同类型但名称不同的实例:
import pathlib
import injector
ConfigFile = pathlib.WindowsPath
UserFile = pathlib.WindowsPath
cfg_file = pathlib.Path.home() / 'settings.cfg'
usr_file = pathlib.Path.home() / 'user.inf'
class AppModule(injector.Module):
def configure(self, binder):
binder.bind(ConfigFile, to=cfg_file) # Guice uses annotatedWith here
binder.bind(UserFile, to=usr_file) # Guice uses annotatedWith here
class App:
@injector.inject
def __init__(self, cfg: ConfigFile, usr: UserFile):
self.config = cfg
self.user = usr
app = injector.Injector(AppModule).get(App)
print(app.config, app.user) # prints the contents of `usr_file` for both
我认为Binder.multibind我有一些可行性,但我的尝试一直没有成功。我能设计的唯一解决方案是pathlib.Path
必须被子类化,并且这些子类显式绑定到它们的实例(可以在injector.Module
中使用@provider和@singleton来管理(。
有没有另一种方法可以做到这一点,而不是解决问题?
可以从typeing_extensions(已经是注入器的依赖项或Python 3.9类型(中使用Annotated。在上面的例子中,只需替换
ConfigFile = pathlib.WindowsPath
UserFile = pathlib.WindowsPath
带有
ConfigFile = Annotated[pathlib.WindowsPath, 'config']
UserFile = Annotated[pathlib.WindowsPath, 'user']
它应该起作用。
打字是完全可能的。NewType,但它可能不会很好地与静态类型的跳棋配合使用。
以下是在python 3.6上测试的完整工作示例:
from injector import Injector, inject, Module, singleton, provider
from typing_extensions import Annotated
from typing import NewType, Callable
# You can use Greeting instead of Annotated[str, 'greeting'] as it's the same type
Greeting = Annotated[str, 'greeting']
class Greeter:
@inject
def __init__(self, greeting: Annotated[str, 'greeting']):
self.greeting = greeting
def greet(self):
print(self.greeting)
class MyModule(Module):
def configure(self, binder):
binder.bind(Greeting, to='Howdy', scope=singleton)
binder.bind(str, to='Hello', scope=singleton)
def main():
injector = Injector([MyModule()])
greeter = injector.get(Greeter)
greeter.greet()
if __name__ == '__main__':
main()
有一点问题,如果你不为Annotated[str, 'greeting']
提供绑定,注入器将使用一个默认的构造函数,它会产生一些东西,但可能不是你所期望的。另一方面,它同样处理str——愉快地构造一个空字符串。
在安装了以下软件包的conda环境中进行测试(注射器使用pip安装(:
# Name Version
injector 0.18.4
libffi 3.0.9
pip 18.1
python 3.6.8
setuptools 40.8.0
sqlite 3.26.0
typing-extensions 3.7.4.3
wheel 0.33.1
xz 5.2.3