2015-11-30 3 views
1

У меня есть 3 модуля: A, B, CPython инъекции зависимостей

A contains a set of classes that B has fetchers for. 

B contains a bunch of singletons that just deal with caching created objects and providing them when requested. Essentially just fetchers. 

C is a list of functions that requires instances of A. 

Операция, которую мне нужно сделать что-то вдоль линий:

C::SomeFunc(): 
    B.getInstance("instance ID") 


B::getInstance(someID: str) -> A: 
    -look at cache, which is either [] or {} 
    -if it is in cache, return that, else do: A(someID) 

Мой вопрос, как бы вы просматриваете экземпляры этих модулей? Этот вопрос в первую очередь мотивирован моим отсутствием понимания системы распределения памяти Python.

Я мог бы что-то сделать по строкам зависимостей зависимостей на основе конструктора, чтобы получить экземпляр A, B, C, куда им нужно идти, а затем иметь некоторый объект «мастер/бог/контроллер», который просто передает вещи, они должны идти -

, например:

class god(object): 
    def __init__(self): 
     a = A() 
     b = B() 
     c = C(b) 
..... 
..... 
class C(object): 
    def __init__(self, B_instance): 
     self.B = B_instance 
    def SomeFunc(self, instanceID): 
     self.B.getInstance(instanceID) 

, но это, кажется, как взломать.

Любые предложения?

Спасибо!

ответ

2

Я видел несколько пакетов, предлагающих провайдера экземпляров на there on PyPI, если это то, что вы ищете. Лично я не хотел иметь дело с другим объектом для получения экземпляров. Поэтому я создал для себя свою собственную библиотеку (только для Python 3). Вам нужно только @ inject и аннотации.

from py3njection import inject 
from some_package import ClassToInject 

class Demo: 
    @inject 
    def __init__(self, object_to_use: ClassToInject): 
     self.dependency = object_to_use 

demo = Demo() 

Это может быть here. Он в основном создает новый экземпляр при каждом вызове метода.

Тестирование легко с этим, поскольку вы должны передавать только mocks в качестве аргументов, чтобы унифицировать вашу функцию/метод.

Я добавил @singleton тоже.

Если вам нужно еще больше способов создания экземпляров, как описано в системе кэширования, документы объясняют, как легко реализовать свои собственные. Все, что связано с кешем, будет заботиться на заводе, и объекты, которые зависят от них, не должны знать, как их получить.

Но если вы находитесь на Python 2 или вам нужно иметь больше контроля над инъекциями, this could work too. Но вам все равно придется манипулировать провайдером.

+0

Я заинтригован тем, как вы храните ссылку на экземпляр 'singleton' внутри' classmethod'. Я никогда не видел зависимости, введенную статическим методом. Для обеспечения конечного времени жизни и сокращения глобального доступа, как вы думаете, можно хранить «singleton» в контейнере, а не в статическом методе? Например, было бы тривиальным изменением, хранящим его в отдельном классе, который более традиционно управляет зависимостями? – ecoe

0

Недавно я выпустил небольшую библиотеку, которая может помочь вам в этом.Обратная связь очень приветствуется: D

https://github.com/suned/serum

0

@autowired еще один Python 3 декоратор, чтобы обеспечить легкие и чистые инъекции зависимостей:

  • функция не должна быть в курсе автоматического связывания на всех
  • зависимости могут быть ленивы инициализированы
  • вызывающий может явно передать экземпляры зависимостей, если требуется

Turn подобный код:

def __init__(self, *, model: Model = None, service: Service = None): 
    if model is None: 
     model = Model() 

    if service is None: 
     service = Service() 

    self.model = model 
    self.service = service 
    # actual code 

в этот:

@autowired 
def __init__(self, *, model: Model, service: Service): 
    self.model = model 
    self.service = service 
    # actual code 

Нет сложный материал, не требует настройки, никаких рабочих процессов не соблюдается.

Декораторный подход очень минималистский. Возможно, что полноценная структура подходит вам лучше. Для этого существуют отличные модули, такие как Injector.

Смежные вопросы