You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

保持模块依赖规则下使用mediatr与dependency_injector注入报错求助

依赖注入错误排查与解决:AttributeError: 'Provide' object has no attribute 'get_person'

问题背景

模块依赖关系如下:

  • application(依赖domain)
  • domain(无依赖)
  • persistence(依赖application)
  • main.py(依赖所有模块)

使用mediatr和dependency_injector实现依赖注入时,触发错误:

AttributeError: 'Provide' object has no attribute 'get_person'

错误原因分析

  1. 装饰器顺序错误:@inject装饰器放在@Mediator.handler之前,导致dependency_injector无法正确拦截Handler类的实例化,依赖未被注入,self.db仍是Provide对象而非实际的DBConnection实例。
  2. 容器依赖未正确传递:主容器Container中,application_container和persistence_container独立创建,未建立依赖关联,导致ApplicationContainer的dbconnection依赖未被填充。
  3. 接口与实现参数不匹配:IDBConnection定义的get_person参数id类型为str,但DBConnection实现中为int,会触发类型错误。
  4. Wire范围不足:仅对__name__(main模块)进行wire,未覆盖application层模块,导致Handler类的注入逻辑未生效。

修复步骤

1. 调整装饰器顺序

将@inject移至@Mediator.handler之后,确保注入逻辑优先执行:

@Mediator.handler
@inject
class PersonQueryHandler:
    # ... 原有代码 ...

2. 修正主容器的依赖关联

在main.py的Container中,让application_container依赖persistence_container提供的database实例:

class Container(containers.DeclarativeContainer):
    mediator = providers.Singleton(Mediator)
    persistence_container = providers.Container(PersistenceContainer)
    application_container = providers.Container(
        ApplicationContainer,
        dbconnection=persistence_container.database
    )

3. 统一参数类型

修改persistence/storage.py中get_person的参数类型为str,与接口定义一致:

def get_person(self, id: str) -> Person:
    return Person(id=id, name="Razali", gender="Male")

4. 扩大Wire覆盖范围

在main函数启动时,将application层的模块加入wire范围:

container.wire(modules=[__name__, "application.personcontext.queries.person"])

完整修复代码

domain/models.py(无修改)

from dataclasses import dataclass

@dataclass
class Person:
    id: str
    name: str
    gender: str

application/interfaces/database.py(无修改)

from abc import ABC, abstractmethod
from domain.models import Person

class IDBConnection(ABC):
    @abstractmethod
    def get_person(self, id: str) -> Person:
        pass

application/containers.py(无修改)

from dependency_injector import containers, providers
class ApplicationContainer(containers.DeclarativeContainer):
    dbconnection = providers.Dependency()

application/personcontext/queries/person.py(修改装饰器顺序)

from domain.models import Person
from mediatr import Mediator
from application.interfaces.database import IDBConnection
from dependency_injector.wiring import inject, Provide
from application.containers import ApplicationContainer

class PersonQuery:
    def __init__(self, id: str) -> None:
        self.id = id

@Mediator.handler
@inject
class PersonQueryHandler:
    def __init__(self, db: IDBConnection = Provide[ApplicationContainer.dbconnection]) -> None:
        self.db: IDBConnection = db

    def handle(self, request: PersonQuery):
        return self.db.get_person(request.id)

persistence/containers.py(无修改)

from dependency_injector import containers, providers
from application.interfaces.database import IDBConnection
from persistence.storage import DBConnection
from application.containers import ApplicationContainer

class PersistenceContainer(containers.DeclarativeContainer):
    database = providers.Singleton(IDBConnection, DBConnection())
    application_container = providers.Container(
        ApplicationContainer,
        dbconnection=database
    )

persistence/storage.py(修改参数类型)

from application.interfaces.database import IDBConnection
from domain.models import Person

class DBConnection(IDBConnection):
    def get_person(self, id: str) -> Person:
        return Person(id=id, name="Razali", gender="Male")

main.py(修改容器关联与wire范围)

from mediatr import Mediator
from application.personcontext.queries.person import PersonQuery
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide
from persistence.containers import PersistenceContainer
from application.containers import ApplicationContainer

class Container(containers.DeclarativeContainer):
    mediator = providers.Singleton(Mediator)
    persistence_container = providers.Container(PersistenceContainer)
    application_container = providers.Container(
        ApplicationContainer,
        dbconnection=persistence_container.database
    )

@inject
def main(mediator: Mediator = Provide[Container.mediator]):
    response = mediator.send(PersonQuery("1"))
    print(response)

if __name__ == '__main__':
    container = Container()
    container.init_resources()
    # Wire main模块和application的handler模块
    container.wire(modules=[__name__, "application.personcontext.queries.person"])
    main()

验证结果

运行main.py后,将输出:

Person(id='1', name='Razali', gender='Male')

内容的提问来源于stack exchange,提问作者RStyle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:35:10