Zope 实用程序的 ZCML 注册可以接受组件或工厂,这有点令人困惑。
<utility component=".some.Class" />
相对
<utility factory=".some.Factory" />
有什么不同?
Zope 实用程序的 ZCML 注册可以接受组件或工厂,这有点令人困惑。
<utility component=".some.Class" />
相对
<utility factory=".some.Factory" />
有什么不同?
我认为@lennart-regebro 的回答可能有点无意欺骗。这是可以理解的,因为 zope 文档有点模糊。我认为下面是正确的解释,但我必须自己测试才能确定。
在组件和工厂注册中,对 getUtility 的每个后续调用,在初始注册后,都将返回相同的实例。
不同的是,组件方法会将引用的对象注册为要返回的实用程序实例,而工厂方法将调用引用的对象并将结果存储为要返回的实用程序实例。
因此,例如,如果您有一个这样定义的实用程序类;
class MyUtility(object):
implements(IMyUtility)
...
注册它;
<utility factory=".my_module.MyUtility"/>
将在执行 zcml 时创建 MyUtility 的实例并将其存储以供将来对 getUtility 的任何调用;
> a = getUtility(IMyUtility)
> b = getUtility(IMyUtility)
> c = getUtility(IMyUtility)
> a is b is c
True
请注意,我们可以将工厂注册为函数而不是类,它只需要在不带参数的情况下调用时返回您要使用的实用程序的实例。
与组件的等效示例是;
class MyUtility(object):
implements(IMyUtility)
...
my_module_instance_of_utility = MyUtility()
注册它;
<utility component=".my_module.my_module_instance_of_utility"\>
这或多或少等同于工厂示例。唯一的区别是组件示例中返回的实例在my_module
被任何东西(包括注册机制)导入时被实例化,而当使用工厂时,实例在执行 zcml 配置时被实例化,就在它被注册之前。在这两种情况下,对 getUtility 的后续调用都将返回相同的实例。
这些都不会与 IFactory 混淆,它确实提供了一些东西,每次请求时都可以为您提供一个新实例,但 API 略有不同。有关这些的更多信息,请参阅此文档。
工厂创建实用程序,而注册为组件的实用程序是实例。因此,如果您查找注册为组件的实用程序,您每次都会得到相同的对象。但是如果它被注册为工厂,你每次都会得到一个新的实例。